C语言控制台数独游戏,注释详细

效果图




#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <math.h>
#include <time.h>
#include <windows.h>
#include <string.h>
#include <conio.h>
#include <stdarg.h>
#include <ctype.h>
#define MAX 999
#define MAXN 9typedef enum bool
{false,true
} bool; //定义布尔类型的枚举//玩家信息结点
typedef struct _player
{int m;                   //所用分钟数int s;                   //所用秒数char name[20];           //玩家姓名int level;               //游戏难度struct _player* next;    //指向下一个玩家结点
} player;void pause(const char* str, ...); //暂停程序void show(player* easy, player* normal, player* hard); //显示排名情况void order(player* head); //按所用时间从少到多进行排序player* get_record(int level); //获取排名记录void record(player info); //记录玩家的游戏时间bool judge(int* player_res, int* answer); //判断是否回答正确void ready(); //给用户5秒的观察时间int get_time(); //获取时间bool receiver(int* player_res); //获取用户输入void sudoku_level(int* answer, int count); //根据难度初始化初盘void print(int* answer); //打印数独void showHelp(); //显示帮助菜单char printMainMenu(); //显示菜单bool set(int x, int y, int val);void reset(int x, int y);void initXOrd(int* xOrd);   //0~9随机序列bool fillFrom(int y, int val);void initShudu();void get_answer(int* answer);int row_size = 593;   //行数
int col_size = 324;   //列数
int result[81];       //存放结果行的栈
int index = 0;        //栈指针
int sudoku[81] = { 0 }; //存放数独
int time_start = 0; //开始时间
int time_end = 0; //结束时间int sudo[MAXN][MAXN];//sudo最终盘void main()
{int player_res[81] = { 0 };int choice;int** matrix;   //存放数独的01矩阵int answer[81] = { 0 };    //存放答案int option;  //难度选项char menuID; //菜单idplayer* easy;   //容易难度排行player* normal; //简单难度排行player* hard;   //困难难度排行player info;    //玩家信息srand(time(NULL));while (true){initShudu();get_answer(answer);menuID = printMainMenu(); //显示菜单switch (menuID){case '1':printf("玩家名:");scanf("%s", &info.name);if (strlen(info.name) > 20){printf("名字太长!\n");break;}printf("请选择游戏难度:  1.简单\t2.一般\t3.困难\n");scanf("%d", &option);printf("\n");switch (option){case 1:sudoku_level(answer, 75); //挖空答案,生成初盘ready();time_start = get_time();if (!receiver(player_res)){printf("\n您已放弃作答!\t正确答案为:\n\n");print(answer);break;}time_end = get_time();info.m = (time_end - time_start) / 60;info.s = (time_end - time_start) % 60;info.level = 1;if (judge(player_res, answer)){pause("恭喜你成功了!\t用时:  %d:%d\n", info.m, info.s);record(info);}else{printf("\n回答错误!\t正确答案为:\n\n");fflush(stdin);print(answer);pause("按任意键返回...");}break;case 2:sudoku_level(answer, 35);time_start = get_time();ready();if (!receiver(player_res)){printf("\n您已放弃作答!\t正确答案为:\n\n");print(answer);break;}time_end = get_time();info.m = (time_end - time_start) / 60;info.s = (time_end - time_start) % 60;info.level = 2;if (judge(player_res, answer)){printf("恭喜你成功了!\t用时:  %d:%d\n", info.m, info.s);record(info);}else{printf("回答错误!\t正确答案为:\n\n");fflush(stdin);print(answer);}break;case 3:sudoku_level(answer, 30);time_start = get_time();ready();if (!receiver(player_res)){printf("\n您已放弃作答!\t正确答案为:\n\n");print(answer);break;}time_end = get_time();info.m = (time_end - time_start) / 60;info.s = (time_end - time_start) % 60;info.level = 3;if (judge(player_res, answer)){printf("恭喜你成功了!\t用时:  %d:%d\n", info.m, info.s);record(info);}else{printf("回答错误!\t正确答案为:\n\n");fflush(stdin);print(answer);}break;default:pause("no option!");fflush(stdin);break;}break;case '2':easy = get_record(1); //获取对应难度的记录normal = get_record(2);hard = get_record(3);order(easy); //进行排序order(normal);order(hard);show(easy, normal, hard); //显示排名pause("按任意键返回...");break;case '3':showHelp();pause("按任意键返回...");break;case '0':printf("\n拜拜~\n\n");exit(0);default:pause("输入有误!请重新输入...");break;}}
}bool set(int x, int y, int val)
{if (sudo[y][x] != 0)      //非空return false;int x0, y0;for (x0 = 0; x0 < 9; x0++) {if (sudo[y][x0] == val) //行冲突return false;}for (y0 = 0; y0 < 9; y0++) {if (sudo[y0][x] == val)  //列冲突return false;}for (y0 = y / 3 * 3; y0 < y / 3 * 3 + 3; y0++) {for (x0 = x / 3 * 3; x0 < x / 3 * 3 + 3; x0++) {if (sudo[y0][x0] == val) //格冲突return false;}}sudo[y][x] = val;return true;
}void reset(int x, int y)
{sudo[y][x] = 0;
}void initXOrd(int* xOrd)   //0~9随机序列
{int i, k, tmp;for (i = 0; i < 9; i++) {xOrd[i] = i;}for (i = 0; i < 9; i++) {k = rand() % 9;tmp = xOrd[k];xOrd[k] = xOrd[i];xOrd[i] = tmp;}
}bool fillFrom(int y, int val)
{int xOrd[9];initXOrd(xOrd);        //生成当前行的扫描序列for (int i = 0; i < 9; i++) {int x = xOrd[i];if (set(x, y, val)) {if (y == 8)                  //到了最后一行{if (val == 9 || fillFrom(0, val + 1))   //当前填9则结束, 否则从第一行填下一个数return true;}else {if (fillFrom(y + 1, val)) //下一行继续填当前数return true;}reset(x, y);    //回溯}}return false;
}void initShudu()
{srand(time(NULL));/*生成 9宫格*/int i = 0, j = 0;for (i = 0; i < 9; i++) {for (j = 0; j < 9; j++) {sudo[i][j] = 0;}}while (!fillFrom(0, 1));
}void get_answer(int* answer)
{int i = 0, j = 0, k = 0;for (i = 0; i < MAXN; i++){for (j = 0; j < MAXN; j++){answer[k] = sudo[i][j];k++;}}
}char printMainMenu()
{char menuID;system("cls");printf("*************************************\n");printf("*            C语言数独游戏          *\n");printf("*************************************\n");printf("*          1.开始游戏               *\n");printf("*          2.查看排名               *\n");printf("*          3.玩法说明               *\n");printf("*          0.退出游戏               *\n");printf("*************************************\n");printf("*          请选择您的操作           *\n");printf("*************************************\n");fflush(stdin);menuID = getch();return menuID;
}void showHelp()
{printf("选择1 \"开始游戏\" 进入难度选择, 选择对应难度后即可进入游戏;\n");printf("选择2 \"查看排名\" 可以查看所有玩家的排名情况;\n");printf("解答说明:解答需将数独完整写一遍,以空格分割每列,以回车分割每行!!!\n");
}void print(int* answer)
{ //打印数独printf("┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓\n");for (int i = 0; i < 81; i++){if (answer[i] == 0)printf("┃  ");elseprintf("┃ %d", answer[i]);if (i == 80){printf("┃  ");printf("\n");printf("┗━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┛\n");}else if ((i + 1) % 9 == 0){printf("┃  ");printf("\n");printf("┣━━╋━━╋━━╋━━╋━━╋━━╋━━╋━━╋━━┫\n");}}
}void sudoku_level(int* answer, int count)
{             //难度int x, y; //行号、列号int num = 0;srand(time(NULL));for (int i = 0; i < 81; i++)sudoku[i] = answer[i];while (num < (81 - count)){ //挖空x = rand() % 9 + 1;y = rand() % 9 + 1;if (sudoku[(x - 1) * 9 + (y - 1)] != 0){sudoku[(x - 1) * 9 + (y - 1)] = 0;num++;}}
}bool receiver(int* player_res)
{ //接收玩家答案for (int i = 0; i < 81; i++){scanf("%d", &player_res[i]);if (!(player_res[i] >= 1 && player_res[i] <= 9)){ //0 表示玩家放弃fflush(stdin);return false;}}return true;
}int get_time()
{ //获得当前时间秒time_t t;t = time(NULL);return t;
}void ready()
{print(sudoku);printf("你有5秒钟观察时间\n");for (int i = 0; i < 5; i++){printf("● ");Sleep(1000);}printf("\n");printf("观察结束,计时开始,请开始作答。(输入除1~9外,视为放弃作答)\n");printf("解答说明:解答需将数独完整写一遍,以空格分割每列,以回车分割每行!!!\n");printf("==========================================================================\n");
}bool judge(int* player_res, int* answer)
{ //判断玩家答案for (int i = 0; i < 81; i++)if (player_res[i] != answer[i])return false;return true;
}void record(player info)
{ //记录FILE* fp;int M = MAX, S = MAX, LEVEL = MAX;char NAME[20];char remove[100] = { "                                                      " }; //用于记录长度固定化,方便更新记录//通过这种方法,可以直接在一个文件中更新数据,不必要全篇读—改—写,直接修改一行int c = 0;if ((fp = fopen("record.txt", "r+")) == NULL){                                     //文件在cpp同目录下printf("文件不存在,保存失败!"); //虽然会自动生成文件,but以防万一return;}setbuf(fp, NULL); //设置缓冲区rewind(fp);c = ftell(fp); //记录当前行的开头指针位置while (fscanf(fp, "%s %d:%d %d", NAME, &M, &S, &LEVEL) != EOF){if (!strcmp(NAME, info.name) && LEVEL == info.level){ //strcmp比较相同返回0if (info.m < M || (info.m == M && info.s < S)){ //如果是新纪录,则更新fseek(fp, c, SEEK_SET);fputs(remove, fp);                                                 //覆盖旧记录fseek(fp, c, SEEK_SET);                                            //回到该记录的开头位置fprintf(fp, "%s %d:%d %d", info.name, info.m, info.s, info.level); //写入文件fflush(fp);                                                        //清除缓冲区return;}return; //不是新纪录就不插入}fscanf(fp, "\n"); //读取换行c = ftell(fp);}fputs(remove, fp);                                                 //先覆盖固定长度的区域fseek(fp, c, SEEK_SET);                                            //回到覆盖的区域首部fprintf(fp, "%s %d:%d %d", info.name, info.m, info.s, info.level); //在覆盖的区域内插入记录fseek(fp, 0, SEEK_END);                                            //指向尾部fprintf(fp, "\n");                                                 //插入换行符fclose(fp);
}player* get_record(int level)
{ //返回玩家记录的单向链表头结点FILE* fp;int M = MAX, S = MAX, LEVEL = MAX;char NAME[20];player* head = (player*)malloc(sizeof(player));head->next = NULL;if ((fp = fopen("record.txt", "r")) == NULL){printf("文件不存在!");system("pause");exit(1);}setbuf(fp, NULL); //设置缓冲区rewind(fp);while (fscanf(fp, "%s %d:%d %d", NAME, &M, &S, &LEVEL) != EOF){if (LEVEL == level){player* p = (player*)malloc(sizeof(player)); //采用链表strcpy(p->name, NAME);p->m = M;p->s = S;p->next = head->next;head->next = p;}}fclose(fp);return head;
}void order(player* head)
{ //单链表排序player* p;player* q;int temp1;int temp2;char temp3[20];for (p = head->next; p != NULL; p = p->next)for (q = p->next; q != NULL; q = q->next)if (p->m > q->m || (p->m == q->m && p->s > q->s)){ //对换两个结点的内容temp1 = p->m;temp2 = p->s;strcpy(temp3, p->name);p->m = q->m;p->s = q->s;strcpy(p->name, q->name);q->m = temp1;q->s = temp2;strcpy(q->name, temp3);}
}void show(player* easy, player* normal, player* hard)
{ //输出排行int no = 1;player* p1 = easy->next;player* p2 = normal->next;player* p3 = hard->next;printf("==========================================================================\n");printf("\t\t   简单\t\t\t  一般\t\t\t   容易\n");while (p1 != NULL || p2 != NULL || p3 != NULL){printf("NO.%d", no++);if (p1 != NULL){printf("\t\t%s\t%d:%d\t", p1->name, p1->m, p1->s);p1 = p1->next;}if (p2 != NULL){printf("\t%s\t%d:%d\t", p2->name, p2->m, p2->s);p2 = p2->next;}if (p3 != NULL){printf("\t%s\t%d:%d\t", p3->name, p3->m, p3->s);p3 = p3->next;}printf("\n");}
}//暂停程序
void pause(const char* str, ...)
{va_list vl;char buf[500] = { 0 };va_start(vl, str);vsnprintf(buf, 500, str, vl);va_end(vl);printf(buf);getch();printf("\n");
}

项目完整地址

C语言实现数独小游戏相关推荐

  1. C语言编写数独小游戏

    文章目录 1.前言 2.效果展示 3.代码 1.前言 这次数独小游戏的灵感来源于上次力扣做的题目,解数独.正好利用题目余热写了这一款小小游戏. 感兴趣的可以看看题目,哈哈 2.效果展示 3.代码 #p ...

  2. C语言编写2048小游戏

    该博文为原创文章,未经博主同意不得转载,如同意转载请注明博文出处 本文章博客地址:https://cplusplus.blog.csdn.net/article/details/104992424 2 ...

  3. C语言实现2048小游戏

    C语言实现2048小游戏-粤嵌GE6818嵌入式系统实训 部分功能演示视频. 实现的全部功能: 1.字模显示封面组员名字 2.完成2048游戏在板子上的运行 3.成功或者失败需要有标志也可以计分 4. ...

  4. C语言实现2048小游戏---粤嵌GE6818嵌入式系统实训

    C语言实现2048小游戏---粤嵌GE6818嵌入式系统实训 实现的全部功能: 功能演示: 版本介绍 简易版--大佬选这个 完整版--想保研.想得高分.想要装逼的同学选这个 至尊版--零基础的.想要装 ...

  5. C语言 剧情版小游戏

    C语言超简单小游戏,,,剧情版,,, 运行效果图: #include<stdio.h>int main() {/*第一关*/int a,b,c,d,e,f,g,h; // int yx=8 ...

  6. Android Studio实现数独小游戏,休闲益智

    文章目录 一.项目概述 二.开发环境 三.详细设计 3.1 界面设计 3.2 逻辑设计 四.运行演示 五.源码获取 一.项目概述 数独是一种逻辑解谜游戏,它规则稍复杂,解题过程富有挑战性.本次安卓数独 ...

  7. c语言编写数据存储的游戏,c语言经典小程序和c语言编写的小游戏带注释(自动保存的).doc...

    c语言经典小程序和c语言编写的小游戏带注释(自动保存的) 1.写一个定时?关机的小程?序,可以立即关?闭计算机,也可以一段?时间后关闭?计算机. #inclu?de #inclu?de #inclu? ...

  8. matlab 版 数独小游戏 GUI界面设计

    近期,由于各种原因,接触到了matlab版的数独小游戏,需要做GUI界面.由于之前本科的时候自己也做过简单的界面涉及,就以为很简单,结果,piapia打脸.数独中的数字是在table中显示的,为了将题 ...

  9. c语言小游戏10例,C语言的应用 小游戏为例.doc

    C语言的应用 小游戏为例 贪吃蛇游戏设计 姓 名: 学 号: 班 级: 103511 指导老师: 张 印 2012年05月29日 <c语言程序设计>课程期末论文 PAGE I 目 录 TO ...

最新文章

  1. 01-VMware-workstation14安装
  2. LOJ #2733 [JOI2016春季合宿]Sandwiches (DP)
  3. oracle tsn 数据库,【Oracle数据库恢复】ORA-00600[25027]错误解析
  4. 自适应网页设计(转)
  5. gridview 默认编辑按钮改成图片
  6. 2017.9.14 dispatching 思考记录
  7. docker项目部署 php_Docker部署PHP+Vue项目
  8. 标准时间标准Time Zone: GMT,UTC,DST,CST
  9. Linux下的编辑器整理
  10. Tomcat配置访问日志和线程数
  11. SQL Server 2008 误删除数据的恢复
  12. linux drcom客户端配置
  13. 种基于局域网的点对点语音通信
  14. 冬日丹崖风貌--承德碧霞山
  15. WZOI-237猜猜谁是冠军
  16. 2020web前端学习路线
  17. 如何进行monkey测试
  18. 广度优先搜索与深度优先搜索
  19. Java程序编写----个人所得税计算器编写
  20. 苹果频率测试软件gen,【技术干货】进行精准的PCIe 4.0时钟抖动测量

热门文章

  1. 平仓_敞口_外汇结售汇_小记
  2. Locust使用手册--开始使用Locust
  3. 摩托车E 绕桩技巧 半坡起步技巧 过单边桥技巧
  4. 用python通过139邮箱发送Email
  5. 数学运算符 +(加)、-(减)、(乘)、(除)、%(取余;取模)、(整除)、(幂运算)及分支结构
  6. RPC框架入门 学习梁飞的RPC
  7. Django框架介绍之cookie与session
  8. RK平台--EVS模块: (二)EVS框架介绍
  9. .msu格式文件跳过windowupdate检测直接安装方案(vs2015安装提示0x80240037安装失败,KB2999226无法安装)
  10. [OpenAirInterface实战-4] :OAI支持的4G LTE功能集