三子棋规则:
玩家与电脑在3x3的棋盘中进行博弈,先将己方3个棋子连成一条线即可获胜(横、竖、对角线均可),若棋盘已下满均未达成获胜条件即为平局
关于开发的实用性讲解-------分模块编程:
当我们在编程设计某些项目时,我们通常会利用到模块化的思想,即将实现各个项目分成个个可拆分的模块,这样我们就不用把所有代码都写在一个文件中,同时能够多人协同编写不同模块,提高开发效率。
例如这次三子棋的实现:
我们就可以把游戏拆分为两个模块 ,一个是实现游戏的功能 game.c,一个用来调试程序test.c;我们仅需要在test.c中包含game.h即可使用对应的模块函数 (.c文件实现函数的具体功能,.h文件只需存放声明即可)
游戏设计思路:
1.设计整个流程,实现玩家的简单交互
#define _CRT_SECURE_NO_WARNINGS
#include"gmae.h"
int main()
{
int input = 0;
do
{
menu();
printf("请输入:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
//退出游戏
return 0;
default:
printf("无效输入!\n");
break;
}
} while (input);
return 0;
}
以上的代码的实现:通过玩家输入的操作数,进行case情况的判断,从而实现是否进行游玩,同时我们还看到循环中有一个menu()函数,是用来显示一个简单的菜单提醒用户进行操作。如下:
void menu()
{
printf("--------------------\n");
printf("-----1.开始游戏-----\n");
printf("--------------------\n");
printf("-----0.退出游戏-----\n");
printf("--------------------\n");
printf("--------------------\n");
}
2.游戏的具体实现
首先我们要用一个3x3的数组来存放数据,我们可以使用#define来设置棋盘大小的常量,
当我们创建数组时,还需要初始化,方便我们后续棋盘的打印和操作,因为是调用了game()来实现游玩,因此我们在game()创建数组即可
void init_board(char board[ROW][COL])
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
board[i][j] = ' ';
}
}
这样我们得到了一个空的棋盘,同时我们还应该有实现打印棋盘的功能,方便玩家更好地进行操作。
void display_board(char board[ROW][COL])
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
printf(" %c ", board[i][j]);
if (j < COL - 1)
printf("|");
}
printf("\n");
if (i < ROW - 1)
{
for (int k = 0; k < ROW; k++)
{
printf("---");
if (k < ROW - 1)
printf("|");
}
printf("\n");
}
}
}
//
我们在打印数组时,适当打印分割线,注意一些临界条件不打印即可,如最后一排最后一列。
当我们拥有棋盘后,即可进行下棋的操作,实现如下:
玩家
void player_do(char board[ROW][COL])
{
int x = 0;
int y = 0;
while (1)
{
printf("玩家下棋:");
scanf("%d %d",&x, &y);
if (x <= ROW && y <= COL && x > 0 && y > 0 && board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '@';
break;
}
else
printf("输入无效\n");
}
printf("\n");
}
电脑
void compert_do(char board[ROW][COL])
{
int x = 0;
int y = 0;
while (1)
{
x = rand() % ROW;
y = rand() % COL;
if ( board[x][y] == ' ')
{
board[x][y] = 'X';
break;
}
}
printf("电脑下棋:%d %d",x+1,y+1);
printf("\n");
}
需要注意的是,在电脑中,因为数组的下标是从0开始的,因此我们不需要-1;而玩家在进行操作时的输入与下标起始不同,故在赋值时应当-1;其中 rand()函数是用来生成随机数的,要包含头文件 stdlib.h才能使用,因为rand()的随机数有局限,我们可以在game()函数中调用srand来避免
最后我们要判断输赢
char is_win(char board[ROW][COL])
{
for (int i = 0; i < NUM; i++)
{
if (board[0][i] == board[1][i] && board[2][i] == board[1][i] &&board[0][i] == '@')
{
return 'p';
}
if (board[0][i] == board[1][i] && board[2][i] == board[1][i] && board[0][i] == 'X')
{
return 'r';
}
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] == '@')
{
return 'p';
}
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] == 'X')
{
return 'r';
}
if (board[0][0] == board[1][1] && board[2][2] == board[1][1] && board[0][0] == '@')
{
return 'p';
}
if (board[0][0] == board[1][1] && board[2][2] == board[1][1] && board[0][0] == 'X')
{
return 'r';
}
if (board[0][2] == board[1][1] && board[2][0] == board[1][1] && board[2][0] == '@')
{
return 'p';
}
if (board[0][2] == board[1][1] && board[2][0] == board[1][1] && board[2][0] == 'X')
{
return 'r';
}
}
for (int i = 0; i < NUM; i++)
{
for (int j = 0; j < NUM; j++)
{
if (board[i][j] == ' ')
{
return 'c';
}
}
}
return 'm';
}
每次当我们下完棋,或电脑下完棋都要进行判断,如果满足获胜条件就直接return对应的值,
r表示电脑获胜,c表示游戏继续,p表示玩家获胜,m表示平局;最后我们在game()中用
char ret 接受即可,通过判断ret的值来反馈游戏结果。最后通过在game()组合调用各个模块即可实现游戏:
void game()
{
char ret = 'c';
srand((unsigned int)time(NULL));
char board[ROW][COL] = {0};
init_board(board);
while (1)
{
display_board(board);
player_do(board);
ret = is_win(board);
if (ret != 'c')
break;
display_board(board);
compert_do(board);
ret = is_win(board);
if (ret != 'c')
break;
}
switch (ret)
{
case 'p':
display_board(board);
printf("玩家获胜!\n");
break;
case'r':
display_board(board);
printf("电脑获胜!\n");
break;
case 'm':
display_board(board);
printf("平局!\n");
break;
default:
break;
}
}
//
int main()
{
int input = 0;
do
{
menu();
printf("请输入:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
//退出游戏
return 0;
default:
printf("无效输入!\n");
break;
}
} while (input);
return 0;
}