新人上路 遇见的第一关{三子棋} 堂堂登场!

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

个人才刚开始学习c语言,小白一位,如有错误、bug、或者值得优化的地方欢迎各位热心且厉害的大佬指出。

当然小白间的互相讨论也是欢迎的!!!
(‘▽’)♪


一、三子棋的主函数

tips:1.menu()函数 //用于打印游戏的菜单,以及通过玩家选择进行反馈

2.关于头文件:由于主函数和game函数内部都需要引用多个且相同的头文件,所以统一的引用一个自建的头文件,并在该头文件内部统一引用会更加方便。

#include"game三子棋.h"
int main()
{
	char arr[ROW][LINE];
	do {
		int a = menu();
		if (a == 1)
			game(arr);
		else if (a == 0)
		{
			printf("退出游戏");
			break;
		}
		else
			printf("输入错误,请重新输入\n");
	} while(1);
	return 0;
}

二、game函数内部细节(附头文件)

1.头文件

在这里插入图片描述

2.game函数

首先打印出“井字形”的棋盘,并创建一窜二维数组以储存不同“颜色”的棋子(注意一开始要初始化键盘)

void init_board(char board[ROW][LINE])
{
	int a, b;
	for (a = 0; a < ROW; a++)
	{
		for (b = 0; b < LINE; b++)
		{
			board[a][b] = ' ';
		}
	}
}
void game(char board[ROW][LINE])
{
	srand((unsigned int)time(NULL));
	init_board(board);//将数组内容初始为空格
	int i = 0, j = 0,e=0;//打印界面所需
	char t=0;//判断输赢返回值用
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < LINE; j++)
		{
			printf(" %c ", board[i][j]); 
			
			if (j < LINE - 1)//最后一列不打印’|‘
				printf("|");
		}
		printf("\n");
		for (e = 0; e < LINE; e++)
		{
			if (i < ROW - 1)
				printf("___");
			if (e < LINE - 1&&i<ROW-1)//下四行代码用于保证井号下方竖杠打印
				printf("|");
			else if ( e < LINE - 1)
				printf("   |");
		}
		printf("\n");
	}





	do {
		player_input(board);//玩家输入
		Print(board);//打印棋盘
		t=Judge(board);//判断输赢
		if (t == '*' || t == '#' || t == 'n')
			break;
		Sleep(1000);//优化用户体感
		system("cls");
		printf("电脑下棋\n");
		computer_input(board);
		Print(board);//打印棋盘
		t = Judge(board);
		if (t == '*' || t == '#' || t == 'n')
			break;
	} while (1);

	switch (t)
	{
	case '*':
		printf("玩家获胜\n");
		break;
	case '#':
		printf("电脑赢\n");
			break;
	case 'n':
		printf("平局\n");
	}
}

再让玩家输入坐标实现选择(玩家棋子为 ‘*’)

void player_input(char board[ROW][LINE])
{
	printf("玩家选择坐标(x y):");
	int a, b;
	while (1)//用常数真与break配合确保只在正确输入坐标后才进行下一步(或者使用goto,但不推荐)
	{
		scanf("%d %d", &a, &b);
		printf("\n");//优化排版
		if (a > 0 && a < 4 && b>0 && b < 4)
		{
			if (board[a - 1][b - 1] == ' ')
			{
				board[a - 1][b - 1] = '*';
				break;
			}
			else
				printf("该点已被占用,请重新输入:");
		}
		else
			printf("坐标非法,请重新输入:");
	}
}

打印下棋后的棋盘(玩家与电脑下后都利用该函数打印)

void Print(char board[ROW][LINE])
{
	int i = 0, j = 0, e = 0;
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < LINE; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < LINE - 1)//最后一列不打印’|‘
				printf("|");
		}
		printf("\n");
		for (e = 0; e < LINE; e++)
		{
			if (i < ROW - 1)
				printf("___");
			if (e < LINE - 1 && i < ROW - 1)//下四行代码用于保证下方竖杠打印
				printf("|");
			else if (e < LINE - 1)
				printf("   |");
		}
		printf("\n");
	}
}

机器人下棋(种子已在一开始定义过)(棋子为‘#’)

void computer_input(char board[ROW][LINE])
{
	int a, b;
	while (1)
	{
		a = rand() % ROW;
		b = rand() % ROW;
		if (board[a][b] != ' ')
			;
		else
		{
			board[a][b] = '#';
			break;
		}

	}
}

重点来了 判断输赢的部分(不同情况的判断分类已通过注释表明)
(winnumber指获胜所需要的长度,三子棋当然是三啦)

不同的判断条件直接相互平行,所以直接分别判断(此处我使用for,注意每次判断时变量的初始化)

char Judge(char board[ROW][LINE])//设定返回*人赢,#机器赢,n平局,c继续
{
	int a,count;
	int c, d;
	int f, e,flag=0;
	char sym=0;
	//判断/对角线
	count = 0;//每次的初始化是必须的
	for (a = ROW-1; a >=0; a--)
	{
		if (board[a][ROW-1-a] == '*')
			count++;
		if (board[a][ROW-1-a] == '#')//不可用else if
		    count--;
		if (count == WINNUMBER || count == -WINNUMBER)//必须放在里面判断,否则会在a越界后进行判断
			sym = board[a][ROW-1-a];
	}
	
	//判断\对角线
	count = 0;
	for (a = 0; a < ROW; a++)
	{
		if (board[a][a] == '*')
			count++;
		if (board[a][a] == '#')//可用else if
		    count--;
		if (count == WINNUMBER || count == -WINNUMBER)
			sym = board[a][a];
	}
	
	//判断行
	for (c = 0; c < ROW; c++)
	{
		count = 0;//在每行的循环都需要初始化
		for (d = 0; d < LINE; d++)
		{
			if (board[c][d] == '*')
				count++;
			if (count == WINNUMBER || count == -WINNUMBER)
			{
				sym = board[c][d];
				break;
			}
			if (board[c][d] == '#')
				count--;
			if (count == WINNUMBER || count == -WINNUMBER)
			{
				sym = board[c][d];
				break;
			}
		}
		}
		
	//判断列
	for (c = 0; c < ROW; c++)
	{
		count = 0;//在每行的循环都需要初始化
		for (d = 0; d < LINE; d++)
		{
			if (board[d][c] == '*')
				count++;
			if (count == WINNUMBER || count == -WINNUMBER)
			{
				sym = board[d][c];
				break;
			}
			if (board[d][c] == '#')
				count--;
			if (count == WINNUMBER || count == -WINNUMBER)
			{
				sym = board[d][c];
				break;
			}
		}
	}
	//全部条件判断后
	if (sym != '#' && sym != '*')
	{
		for (f = 0; f < ROW; f++)//判断结束或继续
		{
			for (e = 0; e < LINE; e++)
			{
				if (board[f][e] == ' ')
				{
					sym = 'c';
					flag = 1;
					break;
				}
			}
		}
		if (flag == 0)
			sym = 'n';
	}
	return sym;
}

总结

把代码块拼在一起后一份简易三子棋的小程序就做好了!!✧٩(๑^ o^๑)۶✧
(但本人能力有限,还没优化电脑的下棋逻辑,欢迎各位大佬指出这方面的思路!!)

以上就是小白写的第一份比较“复杂”的小程序,如果有什么我没发现的错误欢迎指出!

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值