三子棋游戏你肯定是玩过的,今天我就用c语言实现一个简单的三子棋游戏
这个游戏是玩家输入坐标和电脑和产生随机坐标来实现棋子的摆放。
棋子需要二维数组来存放,将玩家走的棋子用’X‘表示,电脑棋子用‘ * ’,初始化的数组为‘ ’。
先给大家看一下代码:
//game.h文件
#define ROW 3//行
#define COL 3//列
void menu();
void initBoard(char board[][COL]);//初始化棋盘
void printBoard(char arr[][COL]);//打印棋盘
char leapWin(char board[][COL]);//判断输赢
bool boardFull(char board[][COL]);//判断棋盘是否放满
void comMove(char board[][COL]);//电脑走棋
void player(char board[][COL]);//玩家走棋
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<stdbool.h>
#include"game.h"//包含了各函数的声明
void menu()
{
printf("**********************************\n");
printf("********* 1.play **********\n");
printf("**********************************\n");
printf("********* 0.exit **********\n");
printf("**********************************\n");
}
void initBoard(char board[][COL])
{
int i = 0;
int j = 0;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
board[i][j] = ' ';
}
}
}
void printBoard(char arr[][COL])
{
int i = 0;
printf("-----------\n");
for (i = 0; i <ROW; i++)
{
printf(" %c | %c | %c \n", arr[i][0], arr[i][1], arr[i][2]);
printf("-----------\n");
}
}
char leapWin(char board[][COL])
{
int i = 0;
if ((board[i][i] == board[i + 1][i + 1]) && (board[i + 1][i + 1] == board[i + 2][i + 2]))//正对角线形成赢局
{
return board[i][i];
}
else if ((board[i][COL - 1] == board[i + 1][COL - 2]) && (board[i + 1][COL - 2] == board[i + 2][COL - 3]))
//反对角线形成赢局
{
return board[i][COL - 1];
}
for (i = 0; i < 3; i++)
{
if ((board[i][0] == board[i][1]) && (board[i][2] == board[i][1]))//第i行形成赢局
{
return board[i][0];
}
else if ((board[0][i] == board[1][i]) && (board[1][i] == board[2][i]))//第i列形成赢局
{
return board[0][i];
}
}
return -1;
}
bool boardFull(char board[][COL])//判断棋盘是否放满
//已放满,返回true,未满返回false
{
int i = 0;
int j = 0;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (board[i][j] == ' ')
{
return false;
}
}
}
return true;
}
void comMove(char board[][COL])
{
while (1)
{
int row = rand() % ROW;
int col = rand() % COL;
if (board[row][col] == ' ')
{
board[row][col] = '*';
break;
}
}
}
void player(char board[][COL])
{
int row, col;
printf("请输入你要走的棋子坐标:");
while (1)
{
scanf("%d%d", &row, &col);//玩游戏的是普通用户,注意row的范围
if ((row > ROW) || (row<1) || (col<1) || (col > COL))
{
printf("您输入的坐标非法,请重新输入:");
}
else if (board[row - 1][col - 1] == ' ')//因为是数组,所以注意使用用户输入值时要减1,
{
board[row - 1][col - 1] = 'X';
break;
}
else
{
printf("您输入的坐标已被占用,请重新输入:");
}
}
}
int main()
{
char arr[ROW][COL] = { 0 };
srand((unsigned int)time(NULL));
int x;
while (1)
{
menu();
printf("输入你的选择:");
scanf("%d", &x);
system("cls");
if (0 == x)
{
break;
}
else if (1 == x)
{
initBoard(arr);
while (1)
{
system("cls");
comMove(arr);
printBoard(arr);
if ('*' == leapWin(arr))
{
printf("电脑赢!\n");
break;
}
else if (boardFull(arr))
{
printf("平局了!\n");
break;
}
player(arr);
printBoard(arr);
if ('X' == leapWin(arr))
{
printf("你赢了!\n");
break;
}
else if (boardFull(arr))
{
printf("平局了!\n");
break;
}
}
}
else
{
printf("你输入有误。\n");
}
}
return 0;
}
基础不好的同学肯定看起来有点吃力,那我再来分析一下几个函数模块:
- 先来一个函数用来打印棋盘
由于棋子的存放的形式是一个二维数组,打印时也是按照二维数组按行方式来打印,加上一些符号修饰棋盘,这个自己在调试中调整就可以了,还是挺简单的,下面是我的棋盘打印
void printBoard(char arr[][COL])
{
int i = 0;
printf("-----------\n");
for (i = 0; i <ROW; i++)
{
printf(" %c | %c | %c \n", arr[i][0], arr[i][1], arr[i][2]);
printf("-----------\n");
}
}
- 玩家和电脑下棋需要两个函数分别来实现
这两个函数大同小异,都是用来走棋的,但是电脑走棋时用rand产生0-2的随机数,而玩家走棋是由玩家输入坐标的,这两个函数需要注意的玩家是普通人,他们不懂数组,要站在玩家的角度考虑,所以玩家输入的坐标是1-3之间的;因为玩家输入的坐标是不可预见的,因此就需要对玩家输入的坐标合法性判断。这些处理好之后,就可以对合法坐标填入棋子了,但是并不一定那么顺利哦,因为坐标合法,但坐标有可能已经被占用,你不能改变已经下好的棋子,因此你要判断生成的坐标是否有棋,然后选择重新输入还是走棋!考虑到这些后,你就可以写代码了:
void comMove(char board[][COL])//电脑走棋
{
while (1)
{
int row = rand() % ROW;
int col = rand() % COL;
if (board[row][col] == ' ')
{
board[row][col] = '*';//坐标没有被占用,走棋
break;
}
}
}
void player(char board[][COL])//玩家走棋
{
int row, col;
printf("请输入你要走的棋子坐标:");
while (1)
{
scanf("%d%d", &row, &col);//玩游戏的是普通用户,注意row的范围
if ((row > ROW)||(row<1) ||(col<1)|| (col > COL))
{
printf("您输入的坐标非法,请重新输入:");
}
else if (board[row-1][col-1] == ' ')//因为是数组,注意使用用户输入值时要减1,
{
board[row - 1][col - 1] = 'X';
break;
}
else
{
printf("您输入的坐标已被占用,请重新输入:");
}
}
}
- 每次走棋后都有可能形成赢局,那么需要一个判断函数来判断输赢,并返回赢的一方
每次走棋后都有可能出现赢局,赢局肯定是某行或者某列或者棋盘上的正对角线或反对角线上棋子相同;因此在该函数内部对数组进行判断,并返回赢局的棋子,没有形成赢局就返回其他值。
char leapWin(char board[][COL])
{
int i = 0;
if ((board[i][i] == board[i + 1][i + 1]) && (board[i + 1][i + 1] == board[i + 2][i + 2]))//正对角线形成赢局
{
return board[i][i];
}
else if ((board[i][COL - 1] == board[i + 1][COL - 2]) && (board[i + 1][COL - 2] == board[i + 2][COL - 3]))
//反对角线形成赢局
{
return board[i][COL - 1];
}
for (i = 0; i < 3; i++)
{
if ((board[i][0] == board[i][1]) && (board[i][2] == board[i][1]))//第i行形成赢局
{
return board[i][0];
}
else if ((board[0][i] == board[1][i]) && (board[1][i] == board[2][i]))//第i列形成赢局
{
return board[0][i];
}
}
return -1;
}
- 当两方实力相当,棋盘被放满还未分出胜负,则需要一个函数判断棋盘是否被放满
当每次放完棋子后需要判断棋盘是否放满来提示平局。
bool boardFull(char board[][COL])//判断棋盘是否放满
//已放满,返回true,未满返回false
{
int i = 0;
int j = 0;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (board[i][j] == ' ')
{
return false;
}
}
}
return true;
}
- 数组初始化用一个函数来操作
void initBoard(char board[][COL])
{
int i = 0;
int j = 0;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
board[i][j] = ' ';
}
}
}
- 最后加上一个菜单函数就可以啦
void menu()
{
printf("**********************************\n");
printf("********* 1.play **********\n");
printf("**********************************\n");
printf("********* 0.exit **********\n");
printf("**********************************\n");
}
看起来很简单的游戏,做的时候就会发现其实并不简单,其中有很多问题需要解决,
希望以后自己还可以用c语言做出其他有意思的东西。
谢谢观阅,如发现问题,请您指出!