C语言之三子棋(n子棋)-创新互联
目录
创新互联为企业级客户提高一站式互联网+设计服务,主要包括成都网站设计、做网站、app软件开发公司、小程序开发、宣传片制作、LOGO设计等,帮助客户快速提升营销能力和企业形象,创新互联各部门都有经验丰富的经验,可以确保每一个作品的质量和创作周期,同时每年都有很多新员工加入,为我们带来大量新的创意。前言:
一、程序框架
选择界面
1、主程序
2、框架搭接
二、游戏函数
棋盘模块
定义声明及调用
函数声明
函数实现
玩家模块
函数声明及调用
函数实现
电脑模块
函数声明及调用
函数实现
判断模块
函数声明及调用
函数实现
三、整体代码
test.c
game.c
game.h
四、效果演示
前言:
小时候我们都玩过五子棋,就是在一个5*5的棋盘上进行落子分为红黑双方,谁第一个在棋盘上五子成线,谁就赢得比赛 图示如下:
对于这样一个小游戏 我们用c语言该如何实现呢?那我们就要对这个游戏的实现进行分析了,首先,想要下棋我们得有一个棋盘,我们可以用二维数组来表示,棋盘是有了,那实现正常的博弈下棋,应该具备哪些模块呢,分析如下:
- 棋盘显示模块;
- 玩家下棋模块;
- 电脑下棋模块;
- 判断输赢模块;
我们只要把整体框架写好,保证衔接没问题,剩下就是子程序的实现啦 让我们一起试试吧
一、程序框架
我们既然学过了函数,数组,以及各个基础知识,那我们就不能停留在 所有函数都集中在一个main函数中那么low了,这次的三子棋,就让它 高大上一点,我们把函数声明,我们把函数的声明,放在头文件game .h中,游戏部分放在游戏的源文件game.c中,我们在函数test.c中,依次调用即可,显得程序逻辑清晰,简单明了。
选择界面 1、主程序我们将实现部分集成在test.c函数中 在主程序main()调用
int main()
{
test();
return 0;
}
2、框架搭接小时候玩的小霸王,都会有一个 界面拱玩家选择 是否 选择进入游戏,或退出,游戏肯定是不能玩一下就结束,所以我们要循环起来,还得要定义一个玩家选择的变量input,因为不同的选择,去向不同 所以用switch分支;因为首先就得出现选择界面,所以用do while 循环语句,来实现,代码实现如下:
void menu()
{
printf("****************************************\n");
printf("************ 1.play ******************\n");
printf("************ 0.exit ******************\n");
printf("****************************************\n");
}
void test()
{
int input;
do
{
menu();
printf("请输入数字->");
scanf("%d",&input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("欢迎下次来玩\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
二、游戏函数
当玩家进入选择进入游戏后,我们就要有棋盘显示,玩家 和电脑就要开始玩起来了,具体game()函数分析如下
棋盘模块我们需要定义一个棋盘,五子棋我们就五行五列 三子棋就三行三列,所以为了方便修改,我们要define行列,并将他们放在game.h头文件中,还需要将棋盘初始化,并显示出来 具体代码如下:
定义声明及调用#define ROW 5
#define COL 5
//定义一个三行三列的数组(棋盘),用来存放棋子
char board[ROW][COL];
char ret = 0;//判断是下棋结果的变量
//初始化棋盘
init_board( board, ROW, COL);
//屏幕上显示棋盘
print_board(board, ROW, COL);
之前我们提过 我们会在test.c中调用子程序,在game.c写具体实现方法,那棋盘初始化,以及显示应该怎么实现呢,棋盘刚开始出现的时候 我们应该保证棋盘上没人落子,所以初始状态是空白,但是我们也看到了 棋盘是有边框的 所以我们在棋盘显示函数中 应该让边框显示出来。学过二维数组的我们 应该觉得很简单,初始化函数无非是把棋盘上每个元素 初始化为空格,显示函数也就是打印边框,具体代码如下:
函数声明//初始化三子棋
void init_board(char board[ROW][COL],int row,int col);
//打印三子棋
void print_board(char board[ROW][COL], int row, int col);
函数实现//实现棋盘初始化
void init_board(char board[ROW][COL], int row, int col)
{
for (int i = 0; i< row; i++)
{
for (int j = 0; j< col; j++)
{
board[i][j] = ' ';
}
}
}
//实现棋盘显示
void print_board(char board[ROW][COL], int row, int 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 j = 0; j< col; j++)
{
printf("___");
if (j< col - 1)
printf("|");
}
}
printf("\n");
}
}
玩家模块棋盘搭接好啦,那就开始下吧,在玩家下棋的子程序中,就是落子,然后棋盘显示,所以就是写一个玩家下棋的函数 之后,调用一下显示函数
函数声明及调用void player_mover(char board[ROW][COL], int row, int col);
//玩家开始下棋
player_mover(board, ROW, COL);
print_board(board, ROW, COL);
函数实现玩家下棋,就是选择我们想要下的位置 对应棋盘上的二维坐标,生活中我们不可能在棋盘外落子,或者在一个已经落完棋子的地方落子,所以我们要对落子进行判断,当棋盘是空白,我们就可以落子(我们用*代表玩家),如果有棋子了 我们要提示该位置已经被落子,并让他重新落子,如果胡乱选择棋盘外,我们要提醒非法落子并让他重新落子,因为有重新落子,所以我们也需要将玩家下棋的步骤,写进循环中,具体代码如下:
//玩家开始下棋
void player_mover(char board[ROW][COL], int row, int col)
{
printf("请玩家落子\n");
while (1)
{
int x = 0;
int y = 0;
scanf("%d %d", &x,&y);
if (x >= 1 && x<= row && y >= 1 && y<= col)
{
if (board[x-1][y-1] == ' ')
{
board[x-1][y-1] = '*';
break;
}
else
printf("该位置已经被落子\n");
}
else
printf("请输入有效落子数\n");
}
}
电脑模块跟玩家类似,在game.c中实现电脑下棋,主程序中调用,然后再调用显示函数
函数声明及调用//电脑开始下棋
void computer_mover(char board[ROW][COL], int row, int col);
//电脑开始下棋
computer_mover(board, ROW, COL);
print_board(board, ROW, COL);
函数实现因为是电脑落子,所以数字要是随机的,随机数字的实现要用到时间戳 srand、rand函数,随机生成 棋盘上的行列限制的数字,这里不做细讲,我课余时间会补充一起,贴上链接;形成一个坐标之后,我们也要进行相同判断,是否已经落子,具体代码如下:
//电脑开始下棋
void computer_mover(char board[ROW][COL], int row, int col)
{
printf("电脑落子\n");
while (1)
{
int x = rand() % row;//随机生成 0 --row-1 的数字
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
判断模块正常生活中我们玩游戏的时候,下完一次,我们就要去检查,有没有连珠,是我们赢啦,还是电脑赢了 所以每次玩家落完子,或者电脑落完子,我们都要进行一次判断,所以我们需要有一个判断函数,定义个变量接收返回值 并通过返回值判断谁赢。
函数声明及调用//判断输赢
char is_win(char board[ROW][COL], int row, int col);
我们定义当返回值为C时候,游戏继续,说明没有分出胜负,当返回值为*玩家赢,返回值为#电脑赢,如果,当棋盘棋子填满,还无法判定胜负时候,就判断为平齐。
while (1)
{
//玩家开始下棋
player_mover(board, ROW, COL);
print_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
//电脑开始下棋
computer_mover(board, ROW, COL);
print_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
printf("玩家赢\n");
else if(ret == '#')
printf("电脑赢\n");
else
printf("平局\n");
}
函数实现判断输赢,其实考虑的要很多,要判断行、判断列、判断对角线,并将连城线上对应棋盘上的棋子返回,就可以做到判断是电脑赢 还是玩家赢了,棋盘的大小会不同,行列也会对应的进行改变,所以我的判断函数部分,用的是两层for循环,判断,前后元素是否相同,相同计数加一,然后最后都相同的的话,计数会比列数少一,我们依此为判断依据 ,最难想的应该是右上到左下角的对角线判断 我当初是这样想的,对角线 三子棋的话 坐标分别是(0,2)(1,1)(2,0)我发现 行坐标自增1,列坐标就自减1,利用这个规律,就可以讲对角线表示出来上代码 清晰明了:
//判断输赢
char is_win(char board[ROW][COL], int row, int col)
{
//判断行
for (int i = 0; i< row; i++)
{
int count0 = 0;
for (int j = 0; j< col - 1; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j] != ' ')
{
count0++;
}
}
if (count0 == col - 1)
{
return board[i][0];
}
}
//判断列
for (int i = 0; i< row; i++)
{
int count1 = 0;
for (int j = 0; j< col - 1; j++)
{
if (board[j][i] == board[j+1][i] && board[j][i] != ' ')
{
count1++;
}
}
if (count1 == col - 1)
{
return board[0][i];
}
}
// 判断左上到右下的对角线
int count2 = 0;
for (int i = 0; i< row - 1; i++)
{
if (board[i][i] == board[i + 1][i + 1] && board[i][i] != ' ')
{
count2++;
}
}
if (count2 == col - 1)
{
return board[0][0];
}
// 判断右上到左下
int count3 = 0;
for (int i = 0;i|
最后差一步判断是否平局呢,我们单独写一个 平局函数,并只在game.c中调用,就记录棋盘有没有满,没满就继续比赛,满了 就平局,代码如下:
char is_win(char board[ROW][COL], int row, int col)
{
//判断行
for (int i = 0; i< row; i++)
{
int count0 = 0;
for (int j = 0; j< col - 1; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j] != ' ')
{
count0++;
}
}
if (count0 == col - 1)
{
return board[i][0];
}
}
if (is_full(board, row, col) == 1)
{
return 'Q';
}
//继续
//没有玩家或者电脑赢,也没有平局,游戏继续
return 'C';
}
三、整体代码 test.c
#define _CRT_SECURE_NO_WARNINGS 1
// **************三子棋游戏*******************************//
#include "gaem.h"
void game()
{
//定义一个三行三列的数组(棋盘),用来存放棋子
char board[ROW][COL];
char ret = 0;//判断是下棋结果的变量
//初始化棋盘
init_board( board, ROW, COL);
//屏幕上显示棋盘
print_board(board, ROW, COL);
while (1)
{
//玩家开始下棋
player_mover(board, ROW, COL);
print_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
//电脑开始下棋
computer_mover(board, ROW, COL);
print_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
printf("玩家赢\n");
else if(ret == '#')
printf("电脑赢\n");
else
printf("平局\n");
}
void menu()
{
printf("****************************************\n");
printf("************ 1.play ******************\n");
printf("************ 0.exit ******************\n");
printf("****************************************\n");
}
void test()
{
srand((unsigned) time(NULL));
int input;
do
{
menu();
printf("请输入数字->");
scanf("%d",&input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("欢迎下次来玩\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
game.c#define _CRT_SECURE_NO_WARNINGS 1
#include "gaem.h"
// 实现初始化棋盘
void init_board(char board[ROW][COL], int row, int col)
{
for (int i = 0; i< row; i++)
{
for (int j = 0; j< col; j++)
{
board[i][j] = ' ';
}
}
}
//实现棋盘显示
void print_board(char board[ROW][COL], int row, int 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 j = 0; j< col; j++)
{
printf("___");
if (j< col - 1)
printf("|");
}
}
printf("\n");
}
}
//玩家开始下棋
void player_mover(char board[ROW][COL], int row, int col)
{
printf("请玩家落子\n");
while (1)
{
int x = 0;
int y = 0;
scanf("%d %d", &x,&y);
if (x >= 1 && x<= row && y >= 1 && y<= col)
{
if (board[x-1][y-1] == ' ')
{
board[x-1][y-1] = '*';
break;
}
else
printf("该位置已经被落子\n");
}
else
printf("请输入有效落子数\n");
}
}
//电脑开始下棋
void computer_mover(char board[ROW][COL], int row, int col)
{
printf("电脑落子\n");
while (1)
{
int x = rand() % row;//随机生成 0 --row-1 的数字
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
static int is_full(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 is_win(char board[ROW][COL], int row, int col)
{
//判断行
for (int i = 0; i< row; i++)
{
int count0 = 0;
for (int j = 0; j< col - 1; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j] != ' ')
{
count0++;
}
}
if (count0 == col - 1)
{
return board[i][0];
}
}
//判断列
for (int i = 0; i< row; i++)
{
int count1 = 0;
for (int j = 0; j< col - 1; j++)
{
if (board[j][i] == board[j+1][i] && board[j][i] != ' ')
{
count1++;
}
}
if (count1 == col - 1)
{
return board[0][i];
}
}
// 判断左上到右下的对角线
int count2 = 0;
for (int i = 0; i< row - 1; i++)
{
if (board[i][i] == board[i + 1][i + 1] && board[i][i] != ' ')
{
count2++;
}
}
if (count2 == col - 1)
{
return board[0][0];
}
// 判断右上到左下
int count3 = 0;
for (int i = 0;i|
game.h#define ROW 5
#define COL 5
#include#include#include//初始化三子棋
void init_board(char board[ROW][COL],int row,int col);
//打印三子棋
void print_board(char board[ROW][COL], int row, int col);
//玩家下棋
void player_mover(char board[ROW][COL], int row, int col);
//电脑开始下棋
void computer_mover(char board[ROW][COL], int row, int col);
//判断输赢
char is_win(char board[ROW][COL], int row, int col);
四、效果演示
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
本文题目:C语言之三子棋(n子棋)-创新互联
文章源于:http://scyanting.com/article/igdgi.html