三子棋——so easy!

来自一个小白的真实呼声:学校讲的真的不行,要想学好,还是要靠自己的努力!

文章目录

  • 如何写出三子棋呢,接下来就让我一步一步教你吧!
  • 一、首先要想三子棋怎么玩的?只有知道怎么玩才能知道如何设计呀。
  • 二、那设计又从哪几方面想呢?
    • 1三子棋是多人游戏对吧,要有玩家或者电脑人机的,玩家下棋,电脑跟棋怎样实现呢?.
    • 2.首先需要想象一个三子棋的框架,这个框架可以由一个二维数组arr[][]来搞,那一开始这个框架什么都没有需要对二维数组初始化;然后呢这个是想象的,需要打印出来
    • 3.打印棋盘后就要思考开始玩家下棋了;注意玩家下棋,下的棋很有讲究,要看这个棋是否合法,在棋盘范围内,下的地方是否是空的。写代码之前要考虑好这些点。
    • 4.玩家下棋后那电脑跟棋,电脑下棋也是有要求的,需要和玩家下棋的条件一样,下棋是否合法,越界没,有空地方可以下吗?有棋的地方肯定不能下了呀。
    • 5.这时玩家和电脑都可以正常下棋了,下面要想什么呢?下棋就要看谁嬴谁输了呀,每下一步棋都有可能有一方赢或输,所以在每次玩家或电脑下棋之后要进行判断是否有输赢。

    总体就是从以下几个方面思考 

  • 设置一个二维数组,初始化数组(为空白)
  • 打印棋盘
  • 玩家下棋
  • 电脑下棋
  • 判断输赢


前言

提示:这里可以添加本文要记录的大概内容:以上都是我在写代码之前的思路喔,接下来我会用代码来解释其中许多细节部分。还有这里要分装各个函数,这样比较方便使用,我会建立一个test.c文件用来测试游戏,建立一个game.c用来实现定义游戏各函数的功能。然后建立一个game.h头文件用来声明各函数。(函数声明一般都放在头文件中)


一、先弄出一个三子棋基本界面,,嗯,,比较简陋。

int main()
{
    test();//  test()进行测试;
    return 0;
}

然后这个test函数里就放一个简易菜单menu()然后再使用do   while 这个循环,因为至少要显示一遍如果不想玩才可以关掉。菜单中显示输入1,进入游戏输入0退出游戏。所以我梦需要定义一个变量intput 使用switch(intput)来选择。而注意这个  intput这个变量要放在循环体外面定义。如何在里面定义那么后面while(intput)里面的intput就没有效果。intput的使用范围只在循环体里了。然后你也应该可以看到,这时do while()条件结束也就是intput为0时,这就和上面一致了。好啦基本框架弄好了

void meun()
{
	printf("************************\n");
	printf("******   1.play   ******\n");
	printf("******   0.exit   ******\n");
	printf("************************\n");
}
void test()
{   
	int intput;
	
	do
	{
		meun();
		printf("请输入:");
		scanf("%d", &intput);
		switch(intput)
		{
		case 1:  game();//这里输入 1进入游戏
			break;
		case 0:  printf("退出游戏\n");
			break;
		default: printf("输入错误\n");
			break;
		}

	} while (intput);
}

 

 

二、设置一个二维数组,初始化数组为空白。

1.这个二维数组呢,本来应该是3 *3类型。这里可以宏定义两个行与列(为什么呢?)因为如果写3*3了那么这个棋盘就固定了,而如果你想改变这个棋盘大小就可以直接对ROW,COL进行修改,而不用进入函数中对数据进行修改了。

代码如下:这里是放在头文件里的喔。因为要频繁使用所以放在头文件中然后再引用头文件就可以啦~~~引用头文件直接就写#include "game.h"就可以啦。

#pragma once
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3//3行
#define COL 3//3列

2.(在test.c文件里开始完善game()函数)设置字符数组char board[ROW] [COL];自定义一个函数作用是初始化它 Init_board(board, ROW, COL);然后在头文件里声明。void Init_board(char board[ROW][COL], int row,int col);//  初始化函数声明。声明后就要去game.c文件去定义这个函数具体作用啦;

 .接下来就是打印棋盘啦。

 

请叫我抽象派大师,啊啊啊啊啊啊我尽力了……。。。嘶,,太抽象了,,我能说那个方格是数组吗,两边是空白的。然后再打印一个  |   。下面是三个---和一个|,这个其实是两列哈,我把这个看成一次大循环,然后整体就是三个大循环,而决定这个大循环的是ROW行决定的,所以呢,我们定义一个i;

弄一个for (i = 0;i < row;i++)里面呢 就是循环每行(大循环)打印的了,,里面要写的代码是每列是打印什么了,可以设置一个变量j  int j;
        for (j = 0;j < col;j++) 循环 ,看! 先是空格 数组 空格  然后换行重新打印 |  (为什么呢?)注意最后一列是没有 |的这说明  | 可不是循坏 col(3) 次喔,最后一次不打印 |所以这里要写一个条件了 if (j < col - 1)  才可以打印 |。这个循环结束,要手动换行。换行后就要打印---打印三个-然后再打印 | 了 ,这个在列的循环中没什么问题,但问题出现在行的打印中,,注意最后一行的最后是没有打印的。所以这里又要设置条件了,这个- - -   |打印的条件应该是if(i<row)成立才打印。这个就是棋盘的打印了。跟初始化函数一样,在test.c设置函数Print_board(board, ROW, COL);//打印棋盘,在头文件里声明void Print_board(char board[ROW][COL], int row, int col);,在game.c里定义实现。


     

void Print_board(char board[ROW][COL], int row, int col)
{
	int i;
	for (i = 0;i < row;i++)
	{
		int j;
		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");
	}
}

 

 打印后就是这样的啦

四.玩家下棋

test.c里设置函数Player_move(board, ROW, COL);//玩家开始下棋;头文件声明void Player_move(char board[ROW][COL], int row, int col);game.c里实现函数功能 。这里要注意玩家下棋,要注意一般玩家玩这种有下标的游戏,,是从1开始数的而不是像我们程序员从下标为0开始数的所以呢,当玩家要输入的值应该是要在代码上是大的哈,程序上写要减一喔,int x = 0;  int y = 0;  scanf("%d%d", &x, &y);玩家输入两个值,这两个值要合法,不能越界。if (x >= 1 && x <= row && y >= 1 && y <= col)这时是合法的。合法后还要判断下的地方是否有空,如果没空就再找所以这个过程是个循环,然后循坏结束就是如果有空就让board[][]==*并且break跳出循环;

void Player_move(char board[ROW][COL], int row, int col)//玩家先开始下棋;
{
	printf("玩家下棋\n");
	while (1)
	{
		//首先要判断下棋是否合法;范围在哪?
		printf("请输入要下棋的坐标:");
		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");
		}
    }

五. 电脑下棋。

电脑下棋呢,这个就要涉及一个生成随机值的知识点了,,这个我会过几天写个猜数字游戏里面会介绍到。这里就直接写告诉你们怎么使用了,并不详细介绍哈。

rand()函数就是用来生成随机数的函数,调用这个函数之前必须要调用srand()函数,srand()函数里面放一个会变化的数就能使rand()函数生成随机数,而什么是不断变化的呢? 对!就是时间,这里又要使用time(NULL)函数来产生时间戳。这里面没有什么可以要给time()放的就放一个空指针进去。调用rand()函数需要引用头文件<stdlib.h>,time函数需要引用<time.h>头文件。

 大家应该懂得一个数%上n, 得到的数范围就是0~n-1,不懂的现在懂啦,

int x, y;
        x = rand() % row;//x只能是0 1 2 
        y = rand() % col;//y也只能是0 1 2;

这时x,y的值就已经合法了,接下来就考虑电脑下的棋是否有空,跟玩家那个是一样的。只不过电脑下棋是#

void Computer_move(char board[ROW][COL], int row, int col)//电脑下棋,也要判断合法性;
{
	printf("电脑下棋\n");
	while (1)
	{
		int x, y;
		x = rand() % row;//x只能是0 1 2 
		y = rand() % col;//y也只能是0 1 2;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
	

}

 

六.判断是谁赢了:    char is_win(char board[ROW][COL], int row, int col);

玩家走一步,可能会赢,电脑走一步也可能会赢,也可能是平局,也可能是谁都没赢也没平局,继续走。这里要想到,玩家走电脑走玩家走电脑走,这个过程是个循环,而跳出这个循环的条件就是有一方赢了或输了或平局,那就break;跳出循环。这里先如果函数返回 * 则表明玩家赢,返回#则表示电脑赢,返回Q则表示平局。而返回C则表示继续。最上面就已经说过玩家走一次就要判断一次,电脑走一次也要判断一次。所以一旦出现不是C了情况了那就直接break;跳出循环。然后再讨论ret到底是什么。

while (1)
	{
		Player_move(board, ROW, COL);//玩家开始下棋;
		Print_board(board, ROW, COL);//每下完棋都有可能会英所以需要判断一下
		//判断输赢;
		ret =is_win(board, ROW, COL);
			if (ret != 'C')
			{
				break;
			}
		Computer_move(board, ROW, COL);//电脑开始下棋;
		Print_board(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}

	}

接下来就是讨论ret到底是谁了

	if (ret == '#')
	{
		printf("电脑赢了\n");
	}
	else if (ret == '*')
		printf("玩家赢了\n");
	else if (ret == 'Q')
		printf("平局\n");

好啦到这里,test.c基本完成还有最后一个函数(判断输赢)没有声明和定义。char is_win(char board[ROW][COL], int row, int col);声明,然后就是定义了,想一想怎么判断输赢呀,怎样算赢呢,是不是有三个相同的就赢啦,所以有每行有三个相同的,每列有三个相同的,还有对角线相同的情况。下面还是有一定巧妙的,只要是三个*相同就是会返回*然后就是玩家赢了,而如果是三个#相同则就会返回#则是电脑赢了。

 还有一个平局怎么判断呢?这个就简单啦,再写一个函数如果棋盘满了就返回1,否则就返回0;

int  is_full(char board[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0;i < row;i++)
	{
		for (j = 0;j < col;j++)
		{
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}

如果返回1了那表面这个函数平局那就is_win函数就返回Q就行了

	if (is_full(board, ROW, COL) == 1)
	{
		return 'Q';
	}

最后如果这些都没有发生那么 char is_win(char board[ROW][COL], int cow, int col)这个函数就自动返回C表示继续比赛。

最后:到现在基本写完了,看看成品吧。

 

总结:如何写三子棋——思路:

1.初始化数组

2.打印棋盘

3.玩家下棋

4.电脑下棋

5.判断输赢 

如果想要看代码的可以去我的github里看      :  https://github.com/ITwei6   代码在12.3里。感谢大家的观看!谢谢!

 

 

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小陶来咯

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

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

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

打赏作者

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

抵扣说明:

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

余额充值