数组应用实例1 —— 三子棋
文章目录
本章目标:
利用所学知识,编写一个简易的三子棋游戏。
本章内容:
-
标识符常量的定义和头文件的包含
-
主函数
main()
-
测试游戏逻辑
test()
-
菜单界面
menu()
-
游戏实现
game()
-
初始化棋盘
InitBoard()
-
打印棋盘
DisplayBoard()
-
玩家下棋
PlayerMove()
-
电脑下棋
ComputerMove()
-
判断输赢
IsWin()
正文:
一、标识符常量的定义和头文件的包含
库函数所需要的头文件的包含,标识符常量的定义。
//game.h
#include<stdio.h>//printf()、scanf()
#include<stdlib.h>//rand()、srand()、system()
#include<time.h>//time()
#include<windows.h>//Sleep()
#define ROW 3
#define COL 3
二、主函数 main()
主函数里调用测试游戏逻辑的函数,避免主函数的臃肿。
//test.c
int main()
{
//数组应用实例-三子棋
test();//测试游戏逻辑
return 0;
}
三、测试游戏逻辑 test()
测试函数会调用菜单界面函数,提供进入游戏和退出游戏的选择。
//test.c
//测试游戏逻辑函数
void test()
{
srand((unsigned int)time(NULL));//设置随机数种子
int select = 0;
do
{
menu();//菜单界面
printf("请输入你的选择:>");
scanf("%d", &select);
switch (select)
{
case 1:
game();//游戏逻辑
break;
case 0:
printf("退出游戏!\n");
break;
default:
printf("选择错误,请重新输入!\n");
break;
}
} while (select);
}
四、菜单界面 menu()
提供游戏菜单界面的显示。
//test.c
//菜单界面函数
void menu()
{
printf("**************************\n");
printf("******** 1.play ********\n");
printf("******** 0.exit ********\n");
printf("**************************\n");
}
五、游戏实现 game()
包括创建棋盘数组、初始化棋盘、打印显示棋盘、回合制下棋(玩家下棋、电脑下棋)、判断输赢状态。
//test.c
//游戏逻辑函数
void game()
{
char board[ROW][COL] = { 0 };//棋盘数组
//初始化棋盘
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;//如果返回值不是'C',就退出回合制下棋,判断输赢平局
}
//电脑下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//每落一子就判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;//如果返回值不是'C',就退出回合制下棋,判断输赢平局
}
}
//判断棋盘输赢状态
if ('*' == ret)
printf("玩家赢了!\n");
else if ('#' == ret)
printf("电脑赢了!\n");
else
printf("本场平局!\n");
//本局棋盘最终情况
printf("\n该局最终结果:>\n");
DisplayBoard(board, ROW, COL);
system("pause");//请按任意键继续
system("cls");//清屏操作
}
//
//什么情况游戏结束?(返回值)
//玩家赢 -- '*'
//电脑赢 -- '#'
//平局 -- 'D'
//继续 -- 'C'
//
六、初始化棋盘 InitBoard()
将棋盘元素初始化为空格。
1 函数原型
//game.h
//初始化棋盘函数声明
void InitBoard(char board[ROW][COL], int row, int col);
2 函数实现
//game.c
//初始化棋盘函数实现
void InitBoard(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++)
{
board[i][j] = ' ';//将棋盘初始化为空格
}
}
}
七、打印棋盘 DisplayBoard()
打印显示棋盘数据。
1 函数原型
//game.h
//打印显示棋盘函数声明
void DisplayBoard(char noard[ROW][COL], int row, int col);
2 函数实现
//game.c
//打印显示棋盘函数实现
//版本1
//void DisplayBoard(char board[ROW][COL], 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");
// }
// printf("\n");
//}
//版本2
void DisplayBoard(char board[ROW][COL], int row, int col)
{
printf("\n");
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("|");
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");//打印分隔横线
if (j < col - 1)//打印分隔竖线
printf("|");
}
printf("\n");
}
}
printf("\n");
}
八、玩家下棋 PlayerMove()
玩家回合,玩家输入棋盘坐标进行下棋。
1 函数原型
//game.h
//玩家下棋函数声明
void PlayerMove(char board[ROW][COL], int row, int col);
2 函数实现
//game.c
//玩家下棋函数实现
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;//棋盘横坐标
int y = 0;//棋盘纵坐标
printf("玩家回合:>\n");
while (1)
{
printf("请输入坐标(用空格分隔):>");
scanf("%d %d", &x, &y);
//检查坐标是否合法
if ((x > 0 && x <= row) && (y > 0 && y <= col))
{
//如果坐标合法,检查坐标是否未被占用
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';//玩家落子:*
break;//退出本回合下棋
}
else
{
printf("该坐标被占用,请重新落子!\n");
}
}
else
{
printf("坐标非法,请重新输入!\n");
}
}
}
九、电脑下棋 ComputerMove()
电脑回合,电脑随机生成坐标下棋。
1 函数原型
//game.h
//电脑下棋函数声明
void ComputerMove(char board[ROW][COL], int row, int col);
2 函数实现
//game.c
//电脑下棋函数实现
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑回合:>\n");
while (1)
{
//电脑随机生成坐标
x = rand() % row;//0 ~ row-1
y = rand() % col;//0 ~ col-1
//检查坐标是否被未占用
if (board[x][y] == ' ')
{
board[x][y] = '#';//电脑落子:#
break;
}
}
}
十、判断输赢 IsWin()
通过检验行是否相等、列是否相等或者对角线是否相等且是否是非空格字符判断输赢;以及通过棋盘是否已满判断本局游戏是否继续还是最终平局。
1 函数原型
//game.h
//判断输赢函数声明
int IsWin(char board[ROW][COL], int row, int col);
2 IsFull()
函数实现
判断棋盘坐标是否已满。
//game.c
//判断棋盘是否已满函数实现
//使用static限定函数只在本文件中使用
static int IsFull(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++)
{
if (board[i][j] == ' ')
return 0;//没满,棋盘还有空格未填满
}
}
return 1;//满了,棋盘已被填满
}
3 IsWin()
函数实现
//game.c
//判断输赢函数实现
int 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][1];//返回坐标信息
}
}
//判断列
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[1][1] != ' ')
{
return board[1][1];//返回坐标信息
}
//副对角线
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];//返回坐标信息
}
//判断平局(棋盘填满,双方未胜)
if (IsFull(board, ROW, COL) == 1)
{
return 'D';//平局(draw)
}
else
{
return 'C';//继续(continue)
}
}
总结:
本节给出了数组应用实例——三子棋的简单实现,分文件编写了函数声明、函数定义和游戏实现。
感谢您的阅读,如有任何错误,欢迎您的批评指正!