三子棋游戏–数组的实现–(C语言)详解
随着C语言的不断学习,练习也显的很重要,本文通过三子棋小游戏加强了C语言函数,循环,选择,数组等学习基础内容的理解。
1、设计棋盘
2、设计过程,游戏玩家如何走,电脑如何走
3、存储数据判断输赢状态
1)、游戏需要先开始一把,可以用do while语句实现
2)、利用菜单让玩家选择,利用switch语句判断是否开始游戏
3)、do while循环条件用input,当玩家input输入错误时,可跳出switch语句,while(input)判断后重新进入switch
代码如下(示例):
void menu()
{
printf("*************************");
printf("******* 1.play *******");
printf("******* 0.exit *******");
printf("*************************");
}
int main()
{
int input;
do
{
menu();
printf("请输入:<");
scanf("%d", &input);
switch (input)
{
case 1 :
printf("玩三子棋游戏");
break;
case 0 :
printf("退出游戏");
break;
default :
printf("输入错误,重新输入");
break;
}
} while (input);
return 0;
}
1)初始化棋盘,设定棋盘大小
假定3*3的棋盘,棋盘大小固定为3,会有游戏限制,调整为自定义棋盘,棋盘大小可用定义全局变量的方式,
例如:#define ROW 3
三子棋是一个3 * 3的棋盘,存储数据需要一个二维数组,(需要初始化一下数组,不然随机值无法控制,不利于查看)
修改前
代码如下(示例):
void game()
{
char board[3][3];//存储数据
InitBoard(board, 3, 3);//初始化棋盘
DisplayBoard(board, 3, 3);//打印棋盘
}
void InitBoard(char board[3][3],int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void DisplayBoard(char board[3][3], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
if (i < row - 1)
{
printf("---|---|---\n");
}
}
}
调整后,可根据自己选择棋盘大小
void game()
{
char board[ROW][COL];//存储数据
InitBoard(board, ROW, COL);//初始化棋盘
DisplayBoard(board, ROW, COL);//打印棋盘
}
、void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");// |打印次数少 %c 一次
}
printf("\n");
if (i < row - 1)//打印"---|---|---"少于" | | "一次,把空格|看作一个整体
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < row - 1)//打印|次数少于---一次
{
printf("|");
}
}
printf("\n");
}
}
}
棋盘测试样例:
2)玩家,电脑下棋
参数传入,需要判断玩家下棋是否符合规则
—玩家下棋坐标与数组认为的坐标不同,玩家下棋的坐标比数组认为坐标+1(数组下标从0开始),
所以用数组下标时记得-1(x-1,y-1).
—玩家下棋需要先判断输入坐标是否符合范围,符合时还需判断所下坐标是否已经有值,坐标==‘ ’时玩家落子,再跳出循环.
—电脑走,需要用到rand函数产生随机坐标
----rand
(注释)不能 直接调用rand函数(产生随机数,不调用srand产生随机数一样), 要在rand的之前调用srand(设置一个随机起点)。
rand 函数返回了一个0-32767直接的数字
rand和srand 两个函数头文件:
----time函数返回时间戳,time函数返回值类型为整型需要我们强制转换一下(转换成unsigned int),
unsigned int 为srand需要的值,(unsigned int)time (NULL))不想放东西,给time放一个空指针
头文件
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x;
int y;
printf("玩家先走,请输入坐标:>\n");
//玩家输入行走坐标
scanf("%d %d", &x, &y);
while (1)//玩家输入错误时需要再次输入用到循环
{
if (x >= 1 && x <= row && y>=1 && y <= col)//判断坐标是否在范围内
{
if (board[x-1][y-1] == ' ')
{
board[x - 1][y - 1] = '*';
break;//防止死循环,当输入正确时跳出循环
}
else
{
printf("该位置已被占用,请更换坐标");
}
}
else
{
printf("输入坐标超出范围,请重新输入");
}
}
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑走:>\n");
//电脑走,自己可以设定电脑走的坐标范围
int x = rand()%row;
//对rand()生成的随机数取模,将0-32767的所有数转化为余数0-2范围内
int y = rand()%col;//同上
while (1)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
}
3)游戏过程中的情况判断游戏的状态
4种游戏状态:玩家赢–返回*,电脑赢–返回#,平局–返回Q,游戏继续–返回C;
赢得三种结果:
1.判断三行,一行相同即为赢,并排除全是空格的赢法
【注】执行函数时,当一行(列)相同时不用判断(是 * 还是#,Q,C)直接返回一行(列)里的任意一个值
2.判断三列(用循环)
3.判断对角线(直接用数组)
平局–看棋盘中是否还有空格(用双重循环判断)
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')//循环判断棋盘没满
{
return 0;
}
}
}
return 1;
}
char IsWin(char board[ROW][COL], int row, int col)
{
//赢的三种情况判断三行是否相同,但不能等于空格
int i = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][0];
}
}
//判断三列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][i];
}
}
//判断对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
{
return board[0][2];
}
//判断平局,平局返回1,否则返回0
int ret = IsFull(board, ROW, COL);
if (ret == 1)
{
return 'Q';
}
//返回C游戏继续
return 'C';
}
//头文件包含
#include
#include
#include
//符号定义
#define ROW 3
#define COL 3
//函数声明
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘的函数
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerMove(char board[ROW][COL],int row,int col);
//电脑下棋
void ComputerMove(char board[ROW][COL],int row ,int col);
//判断游戏是否有输赢
//玩家赢--*,电脑赢--#,平局--Q,游戏继续--C
char IsWin(char board[ROW][COL], int row, int col);
void InitBoard(char board[ROW][COL],int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");// |打印次数少 %c 一次
}
printf("\n");
if (i < row - 1)//打印"---|---|---"少于" | | "一次,把空格|看作一个整体
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < row - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x;
int y;
printf("玩家先走,请输入坐标:>\n");
//玩家输入行走坐标
scanf("%d %d", &x, &y);
while (1)//玩家输入错误时需要再次输入用到循环
{
if (x >= 1 && x <= row && y>=1 && y <= col)//判断坐标是否在范围内
{
if (board[x-1][y-1] == ' ')
{
board[x - 1][y - 1] = '*';
break;//防止死循环,当输入正确时跳出循环
}
else
{
printf("该位置已被占用,请更换坐标");
}
}
else
{
printf("输入坐标超出范围,请重新输入");
}
}
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑走:>\n");
//电脑走自己可以设定电脑走的坐标范围
int x = rand()%row;
int y = rand()%col;
while (1)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')//循环判断棋盘没满
{
return 0;
}
}
}
return 1;
}
char IsWin(char board[ROW][COL], int row, int col)
{
//赢的三种情况判断三行
int i = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][0];
}
}
//判断三列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][i];
}
}
//判断对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
{
return board[0][2];
}
//判断平局,平局返回1,否则返回0
int ret = IsFull(board, ROW, COL);
if (ret == 1)
{
return 'Q';
}
//继续
return 'C';
}
void menu()
{
printf("*************************\n");
printf("******* 1.play *******\n");
printf("******* 0.exit *******\n");
printf("*************************\n");
}
void game()
{
char board[ROW][COL];//存储数据
InitBoard(board, ROW, COL);//初始化棋盘
DisplayBoard(board, ROW, COL);//打印棋盘
int ret = 0;
while (1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
//电脑下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家赢了\n");
}
else if (ret == '#')
{
printf("电脑赢了\n");
}
else if (ret == "Q")
{
printf("平局\n");
}
DisplayBoard(board, ROW, COL);
}
int main()
{
int input;
srand((unsigned int)time(NULL));//使用一次所以在主函数中调用
do
{
menu();
printf("请输入:<");
scanf("%d", &input);
switch (input)
{
case 1 :
game();
break;
case 0 :
printf("退出游戏");
break;
default :
printf("输入错误,重新输入");
break;
}
} while (input);
return 0;
}
以上就是三子棋代码详解内容,三子棋代码对我们C语言练习有很大帮助,对于函数的使用,数组循环的使用有了更深的理解,文章可能有错误,如有发现希望各位读友指正。