三子棋
Posted 快乐江湖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三子棋相关的知识,希望对你有一定的参考价值。
文章目录
一:三子棋游戏介绍
三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉、一条龙、井字棋等。将正方形对角线连起来,相对两边依次摆上三个双方棋子,只要将自己的三个棋子走成一条线,对方就算输了。但是,有很多时候会出现和棋的情况。
二:C语言实现三子棋
这里不采用拿出完整代码的方式,讲解每一部分代码是什么作用,我们从0开始,一步一步实现整个逻辑
(1)新建文件
整个游戏需要三个文件,第一个是头文件“chess.h”用于声明函数,宏定义等,第二个是“chess_achive.c”用于实现头文件中所声明函数的功能,第三个是"chess.c"用于控制整个游戏逻辑。
(2)逻辑流程
第一:先打印菜单,与用户对话
如下
但是这里有一个问题,如何如何让用户“挑选”选项,然后程序再进行对应操作呢。我们可以这样,使用变量input接受用户输入的数据,再用switch函数进行操作
第二:游戏函数
首先游戏函数大体上的逻辑如下
- 在现实生活中,我们下棋用的是棋子,但是在电脑上不可能有真的棋子。所以我们需要某种东西去代替它,最能想到的就是用符号,而符号是一个字符,所以我们可以建立一个字符数组去存储这些棋子。
为了方便我们建立一个3×3的棋盘,所以字符数组也设置为相应大小,这里需要注意的一点是,为了整个游戏的可变性,不至于以后棋盘的大小只能是3×3,所以我们实现要在头文件中进行宏定义,以后改变棋盘大小时只需在此处更改
- 字符数组建立好之后,我们就要“洗牌”,意思就是让棋盘面清空,所谓清空实际意思就是字符数组每个字符都是空的。这一过程就不用详细叙述了
- 现实中的棋盘是能摸得着的,但是显示屏上棋盘却不是真的,或者说它就是不是棋盘,可以理解为打印出几条线,让棋子分割开来。所以这一步我们得设计一个函数去显示出棋盘,不止再这里要用,再后面电脑和人下棋的时候,也是需要下一步棋就显示棋盘的。
我们的棋盘(3×3)样式基本就是下面这样:图中空白的位置就是棋子的落脚位置,线条就是棋子的分割线
相应代码部分我们的思路是,打印一个数据,打印一条竖分界线,其中一个数据占用三列,一行打印完之后再打印下一行
这里稍稍美中不足的就是最后一列数据分界线被打印出来二路,显得很别扭,可以这样操作
- 接着就是电脑和玩家开始下棋
所以要分别实现玩家下棋和电脑下棋的函数
用户下棋时,让用户输入坐标以确定棋子,这里需要注意的一点是,用户不知道数组下标是从0开始的,所以用户认为第一个位置坐标为(1,1),但是实际上(0,0),所以在处理这一点时要注意转换
用户输入坐标时有可能会造成非法输入,所以要用循环确保用户输入正确,同时想要落子就要确保落子的位置必须是空的。
电脑下棋时一定是随机的,所以要使用到随机数。对于随机数有这样的三步,第一引入头文件“time.h”,第二利用时间戳时间随机种子,第三进行取余操作,确保随机数所取范围。
随机数设好之后,电脑下棋就很好写了
- 重要的落子步骤完成之后,就需要注意一点,因为每一次落子有可能胜负就出来了。所以在用户或者是电脑下棋完成之后,立马就要对整个棋盘进行判断。我们编写一个判断输赢的函数,输赢无非有四种情况(玩家赢,电脑赢,平局即棋盘满了,继续),所以首先要判断棋盘是否满了,棋盘满了一定没有分出胜负,就是平局。棋盘没有满那就对其横竖斜进行判断
三:演示
玩家赢
电脑赢
平局
四:完整代码
头文件
#define COW 3
#define COL 3//定义这个棋盘的行和列
void Initboard(char board[COW][COL], int cow, int col);//初始化棋盘函数声明
void Displayboard(char board[COW][COL], int cow, int col);//打印骨架函数声明
void Playerboard(char board[COW][COL], int cow, int col);//玩家走
void Computerboard(char board[COW][COL], int cow, int col);//电脑走
//Iswin返回值为字符型,通过返回特定字符来判断输赢情况
/*
1:返回“*”表示玩家赢
2:返回“#”表示电脑赢
3:返回“C”表示继续
4:返回“Q”表示平局
*/
char Iswin(char board[COW][COL], int cow, int col);
函数实现文件
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "SanZiQi_head.h"
void Initboard(char board[COW][COL], int cow, int col)//初始化棋盘
for (int i = 0;i < cow;i++)
for (int j = 0; j < col; j++)
board[i][j] = ' ';
void Displayboard(char board[COW][COL], int cow, int col)//打印棋盘骨架(这里涉及到一些概念见笔记)
int i = 0;
for (i = 0; i < cow; i++)//先打印数据行和行分界线
int j = 0;
for (j = 0; j < col; j++)//打印数据行
printf(" %c ", board[i][j]);//一个数据占三行,“ %c ”
if (j < col - 1)//每打印一个数据,画一条数据分界线,其中为了美观最后一列的数据的分界线不用打印
printf("|");
printf("\\n");//打印完一行数据换一行
if (i < cow - 1)//打印下一行之前,打印一条行分界线,为了美观最后一行的行分界线不用打印
for (j = 0; j < col; j++)//打印行分界线
printf("---");
if (j < col - 1)
printf("|");//打印行分界线的竖分界线,还是一样最后一列的数据分界线不用打印
printf("\\n");//打印完一行行数据分界线
void Playerboard(char board[COW][COL], int cow, int col)//用户输入
int x = 0;
int y = 0;
printf("你走:\\n");
while (1)//用户输入的坐标可能会出现非法情况,所以要用循环,一旦出现非法,就再接受
printf("请输入坐标\\n");
scanf("%d%d", &x, &y);//接受用户坐标
if (x >= 1 && x <= cow && y >= 1 && y <= col)//这里注意用户是不知道数组下标是从0开始的,所以我们判断的时候要考虑用户认为第一个坐标是1,1
if (board[x - 1][y - 1] == ' ')//输入合法并且要输入的位置没有东西
board[x - 1][y - 1] = '*';//那么就用一个“*”表示用户输入
break;//一旦输入成功跳出循环,就该电脑输入了
else
printf("该位置已经被占用了\\n");
else
printf("输入越界,请重新输入\\n");//非法情况
void Computerboard(char board[COW][COL], int cow, int col)
int x = 0;
int y = 0;
printf("电脑走\\n");
while (1)//电脑也可能输入错误,所以也要循环
x = rand() % cow;//这种方式能保证x取值为0,1,2,
y = rand() % col;//这种方式能保证y取值为0,1,2,
if (board[x][y] == ' ')
board[x][y] = '#';//如果正确输入电脑的符号
break;//输入完成跳出循环
int Isfull(char board[COW][COL], int cow, int col)//注意这个函数不用在头文件里声明,因为Iswin被声明了,Isfull在Iswin的本文件前面调用了
int i = 0;
int j = 0;
for (i = 0; i < cow; i++)
for (j = 0; j < col; j++)
if (board[i][j] == ' ')
return 0;//一旦找到空,表明棋盘没有满
return 1;//执行到这说明满了
char Iswin(char board[COW][COL], int cow, int col)
//判断输赢时,横三行,竖三列,和主副对角只要元素相同就代表某方赢,返回对应字符即可
int i = 0;
int j = 0;
//判断横三行
for (i = 0; i < cow; 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[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
return board[1][1];
//以上用于判断电脑还是玩家赢
//接下来判断是否平局和继续
if (1 == Isfull(board, COW, COL))//如果棋盘满了就表示平局
return 'Q';
return 'C';//没有赢,也没有平局那就继续
逻辑控制文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "SanZiQi_head.h"
#include <stdio.h>
//本游戏用到game.c,game.h
void menu()//菜单
printf("************三子棋对战游戏**************\\n");
printf("***********1.play 0.exit***************\\n");
printf("*****************************************\\n");
void game()
char ret = 0;//接受字符,用于判断输赢情况
char board[COW][COL] = 0 ;//建立一个二维数组,形式上看起来就像一个棋盘
Initboard(board, COW, COL);//初始化棋盘,所有元素空格,看起来就像没有元素一样
Displayboard(board, COW, COL);//打印棋盘骨架
while (1)//电脑和玩家循环下棋
Playerboard(board, COW, COL);//玩家先走
Displayboard(board, COW, COL);
//玩家走完立马判断情况
ret = Iswin(board, COW, COL);//ret用于接受Iswin函数返回输赢的特征字符情况
if (ret != 'C')//如果ret不是C,说明已经判断出输赢情况了,及立马跳出while,去判断情况
break;
Computerboard(board, COW, COL);//电脑再走
Displayboard(board, COW, COL);
ret = Iswin(board, COW, COL);
if (ret != 'C')//如果ret不是C,说明已经判断出输赢情况了,及立马跳出while,去判断情况
break;
if (ret == '*')
printf("你赢了\\n");
else if (ret =='#')
printf("电脑赢了\\n");
else
printf("平局\\n");
void test()//开始游戏
srand((unsigned int)time(NULL));
int input = 0;
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(void)
test();
return 0;
以上是关于三子棋的主要内容,如果未能解决你的问题,请参考以下文章