C语言—————三子棋,步步分解

一.三子棋轮廓

  1. 游戏开始
  2. 打印目录,并让玩家选择是否玩游戏
  3. 当玩游戏我们需要一个棋盘
  4. 用二维数组存放下子位置,创建棋盘模样
  5. 玩家走电脑走
  6. 判断输赢
  7. 游戏结束

实现目录

1.打印目录

2.玩家选择

3.创建一个二维数组

4.打印棋盘

5.玩家走

6.电脑走/玩家走

7.判断输赢

全部代码


 

二.根据轮廓来实现三子棋

附:下面的内容,皆以代码的形式直接展示,其代码为什么这么些附有注释。

1.打印目录

d48f1ab1133c41c9be5d17baf7e6d0c0.png

void mnue()
{
	printf("**********************\n");
	printf("*******  1. play  ****\n");
	printf("*******  0. exit  ****\n");
	printf("**********************\n");
}


...

mnue();

....

 

 

2.玩家选择

9b8342f0cbb04316807d7e7b559f75c6.png

void mnue()
{
	printf("**********************\n");
	printf("*******  1. play  ****\n");
	printf("*******  0. exit  ****\n");
	printf("**********************\n");
}

int main()
{
	int input = 0;
	do//首先利用do while循环的先执行一道再判断进行打印目录并让玩家选择是否玩游戏
	{
		mnue();
		printf("是否玩游戏(1/0):>");
		scanf("%d",&input);//玩家选择1.玩游戏 0.退出游戏
		switch (input)
		{
		case 1:
			printf("猜数字游戏\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}

	} while(input);

	return 0;
}

当我们选择1玩游戏时我们就会来到case1,并进到game()函数内

 

game函数:

3.创建一个二维数组

 daacc82eef7f40c18cc52efe0dd1276f.png   

分析:创建这些空间,即可以下子的空位置,并初始化成空格

//        test.c

#include"game.h"

void game()
{
char arr[ROW][COL] = {0};
//创建一个ROW行的,COL列的数组arr来存等一下 下子的位置

init(arr, ROW, COL);

...


//      game.h

#define ROW 3
#define COL 3   
//在头文件中用define定义常量这样就可以更方便的去修改这个棋盘的行,列
//如此时打印的棋盘大小是3*3的我们若想增大棋盘就可以直接在define处修改而不是
//一个一个的去修改行与列

void init(char arr[ROW][COL], int r, int c);//inti函数的声明,为了让inti函数可以在game.c中用

//         game.c

void init(char arr[ROW][COL], int r, int c)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < r; i++)
	{
		for (j = 0; j < c; j++)
		{
			arr[i][j] = ' ';//现将数组内的所有内容,先置成空格
		}
	}
}

        此处用到了分源管理,创建一个自己的头文件(管理定义的常量,和函数的声明,和库函数所需的头文件),既然是头文件我们在使用时就要定义(#include"game.h")

4.打印棋盘

 

 9bd242dd545b47d58a019acae0d29aad.png

观察:可以发现棋盘由第一行和第二行循环打印而成(只不过有个别限制)的一组

分析:首先用循环打印第一行(第一行由将要下的子 %c 和 | 组成 ),并且限制不打印最后一个  ' | '

           其次用循环打印第二行( 第二行 由 --- 和 | 组成),并且限制不打印最后一个  ' | '

           最后把第一行与第二行看成一组循环打印,并且限制不打印最后一个第二行

//test.c
...
void game()
{
...

print(arr, ROW, COL);
 
...


//game.h


//打印棋盘

void print(char arr[ROW][COL],int r,int c);//声明



//game.c

void print(char arr[][COL], int r, int c)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < r; i++)//打印时要小于行的大小
	{
    //此处分开一行一行打印是为了当我们改变行列时可以跟着改变打印                                                                                                    
    //的行列数

		for (j = 0; j < c; j++)		//打印时要小于列的大小
        {
			printf(" %c ", arr[i][j]);  //第一行由将要下的子 %c 和 | 组成 
			if (j < c - 1) //其中 | 在最后不用打印
				printf("|");
		}
		printf("\n");
		if (i < r - 1)    //第二行在最后不用打印
		{
			for (j = 0; j < c; j++)
			{
				printf("---")  ;  //第二行 有 --- 和 | 组成
				if (j < c - 1)  // | 在最后不用打印
			    printf("|");

			}
			printf("\n");
		}

	}

开始下棋:玩家走一步,电脑走一步,不停的走直到一方胜利或则平局

5.玩家走

4e8648f6b3124ace892c27f6e29ba56a.png

分析:当玩家输入坐标(因正常人并不知道数组下标所以要对应的-1)时在对应的坐标下入子('0') ,并打印玩家下子后的棋盘

//test.c
....

while(1)
{

play_move(arr, ROW, COL);
print(arr, ROW, COL);

...


game.h

...

//玩家走
void play_move(char arr[ROW][COL], int r, int c);


game.c

void play_move(char arr[][COL], int r, int c)
{
	int x = 0;
	int y = 0;


	while(1)
	{
		printf("玩家走:>");
		scanf("%d %d", &x, &y);
		printf("\n");
		if (x > 0 && x <= ROW && y > 0 && y <= COL)//首先判断玩家下的子是否满足行列范围
		{
            //x-1 ,y-1 因为一般人认为第一行第一列为1 1
			if (arr[x - 1][y - 1] == ' ')//当这个位置是空的就可以下子
			{
				arr[x - 1][y - 1] = 'O';//将这个位置下成 '0'
				break;
			}
			else
			{
				printf("该空已被占请重新输入\n");
			}
		}
		else
		{
			printf("错误输入,请重新输入\n");
		}
	}

}

6.电脑走

6b8cb87df7fe45f0a722eccbad01f2a1.png

分析:要让电脑走,其实就是传入两个随机值并将产生坐标下入子'X' 

//test.c
void game()
{
while(1)
{
    ...
    comput_move(arr, ROW, COL);
    print(arr, ROW, COL);
    ...


}

int main()
{
    srand((unsigned int)time(NULL));

....

game.h


//电脑走
void comput_move(char arr[ROW][COL], int r, int c);



game.c

void comput_move(char arr[][COL], int r, int c)
{
	printf("电脑走\n");
	while (1)
	{
		int x = rand() % r;//产生随机数模上行表示其大小范围是 0~r-1(2)
		int y = rand() % c;//同上列的范围是0~r-1(2)
		if (arr[x][y] == ' ')//不用想人一样加else,电脑若不对就再循环
		{
			arr[x][y] = 'X';
			break;
		}
	}

}

7.判断输赢

分析:

赢:

一行或者一列全部都为一种棋子时;对角线全部都为一种棋子时

平局:

先判断输赢,当输赢判断完发现并没有人赢时,再看这个二维数组的空间内是否还有空位置,若没了就代表平局,

谁都没赢:继续比赛

test.c

while()
{
    ...
    char re = 0;//储存返回的值
    ...
    
    re = is_win(arr, ROW, COL);//函数判断是否赢了,并返回一个值

    if (re != 'Q')//当返回的并不是继续游戏时
    {
	    break;//跳出下子循环
    }

    ...
    
}

if(re == 'O')
	{
		printf("恭喜玩家赢了\n");
	}
	else if (re == 'B')
	{
		printf("平局\n");
	}
	else
	{
		printf("电脑都比你吊\n");
	}



game.h


char is_win(char arr[ROW][COL], int r, int c);


game.c


int is_full(char arr[ROW][COL], int r, int c)
{
	int i = 0;
	int j = 0;
	int k = 0;
	for (i = 0; i < c; i++)
	{
		for (j = 0; j < r; j++)
		{
			if (arr[i][j] == ' ')//用循环判断数组内还有没有空格
			{
				k = 1;
				return k;//当有空格时将k置成1返回,代码有空格
			}

		}
	}
	return k;//当k没有变成1,就会返回初始化的k 0

}


char is_win(char arr[][COL], int r, int c)
{
	int j = 0;
	for (j = 0; j < r; j++)//用一行一行,一列一列的查
	{
		if (arr[j][0] == arr[j][1]&&arr[j][1] == arr[j][2] && arr[j][1] !=' ')
			//判断一行
            return arr[j][1];//当一行全部相等时返回其中的一个子
		if (arr[0][j] == arr[1][j] && arr[1][j] == arr[2][j] && arr[1][j] !=' ')
			//判断一列
            return arr[1][j];
	}
     //判断两对角线是否相等
	if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ')
		return arr[1][1];
	if(arr[1][2] == arr[1][1] && arr[3][1] == arr[1][1] && arr[1][1] != ' ')
		return arr[1][1];

    //判断还有没有空位置若没则平局
	int f = is_full(arr, ROW, COL);
	if (f == 0)//如果返回0 就代表没有空格了平局了
	{
		return 'B';
	}

	return 'Q';//当返回1时就代表还有空格可以继续游戏
}

 

 


全部代码

test.c

 #define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void game()
{
	while (getchar() != '\n')
	{
		;
	}
	char re = 0;//声明存储是否赢了的标志
	char arr[ROW][COL] = {0};
	init(arr, ROW, COL);
	print(arr, ROW, COL);
	while (1)
	{
		play_move(arr, ROW, COL);
		print(arr, ROW, COL);
		/*printf("电脑走\n");*/
		Sleep(2000);
		re = is_win(arr, ROW, COL);
		if (re != 'Q')
		{
			break;
		}
		system("cls");
		comput_move(arr, ROW, COL);
		print(arr, ROW, COL);
		re = is_win(arr, ROW, COL);

		if (re != 'Q')
		{
			break;
		}

	}
	if(re == 'O')
	{
		printf("恭喜玩家赢了\n");
	}
	else if (re == 'B')
	{
		printf("平局\n");
	}
	else
	{
		printf("电脑都比你吊\n");
	}



}
void mnue()
{
	printf("**********************\n");
	printf("*******  1. play  ****\n");
	printf("*******  0. exit  ****\n");
	printf("**********************\n");
}

int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		mnue();
		printf("是否玩游戏(1/0):>");
		scanf("%d",&input);
		switch (input)
		{
		case 1:
			printf("猜数字游戏\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}

	} while(input);




	return 0;
}

 

game.h:
 

#pragma once
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<time.h>

#define ROW 3
#define COL 3
//棋盘初始化
void init(char arr[ROW][COL], int r, int c);
 
//玩家走
void play_move(char arr[ROW][COL], int r, int c);
//电脑走
void comput_move(char arr[ROW][COL], int r, int c);

//打印棋盘
void print(char arr[ROW][COL], int r, int c);


//判断输赢
char is_win(char arr[ROW][COL], int r, int c);

 

game.c:

 #define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"


int is_full(char arr[ROW][COL], int r, int c)
{
	int i = 0;
	int j = 0;
	int k = 0;
	for (i = 0; i < c; i++)
	{
		for (j = 0; j < r; j++)
		{
			if (arr[i][j] == ' ')
			{
				k = 1;
				return k;
			}

		}
	}
	return k;

}

void init(char arr[ROW][COL], int r, int c)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < r; i++)
	{
		for (j = 0; j < c; j++)
		{
			arr[i][j] = ' ';
		}
	}
}

void print(char arr[][COL], int r, int c)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < c; i++)
	{
		for (j = 0; j < c; j++)
		{
			printf(" %c ", arr[i][j]);
			if (j < c - 1)
				printf("|");
		}
		printf("\n");
		if (i < r - 1)
		{
			for (j = 0; j < c; j++)
			{
				printf("---");
				if (j < c - 1)
					printf("|");

			}
			printf("\n");
		}

	}

}

void play_move(char arr[][COL], int r, int c)
{
	int x = 0;
	int y = 0;


	while(1)
	{
		printf("玩家走:>");
		scanf("%d %d", &x, &y);
		printf("\n");
		if (x > 0 && x <= ROW && y > 0 && y <= COL)
		{
			if (arr[x - 1][y - 1] == ' ')
			{
				arr[x - 1][y - 1] = 'O';
				break;
			}
			else
			{
				printf("该空已被占请重新输入\n");
			}
		}
		else
		{
			printf("错误输入,请重新输入\n");
		}
	}

}

void comput_move(char arr[][COL], int r, int c)
{
	printf("电脑走\n");
	while (1)
	{
		int x = rand() % c;
		int y = rand() % r;
		if (arr[x][y] == ' ')
		{
			arr[x][y] = 'X';
			break;
		}
	}

}

char is_win(char arr[][COL], int r, int c)
{
	int i = 0;
	int j = 0;
	for (j = 0; j < r; j++)
	{
		if (arr[j][i] == arr[j][i + 1] && arr[j][i+1] == arr[j][i+2] && arr[j][i+1] != ' ')
			return arr[j][i+1];
		if (arr[i][j] == arr[i+1][j] && arr[i+1][j] == arr[i+2][j] && arr[i+1][j] != ' ')
			return arr[i+1][j];
	}

	if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ')
		return arr[1][1];
	if(arr[1][2] == arr[1][1] && arr[3][1] == arr[1][1] && arr[1][1] != ' ')
		return arr[1][1];

	int f = is_full(arr, ROW, COL);
	if (f == 0)
	{
		return 'B';
	}

	return 'Q';
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

溟洵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值