彩色版五子棋
#include <windows.h>
#include <conio.h>
#include <stdio.h>
int W = 13, S, M = 0, *m, c = 1, r = 2, z, i, j, k, *p;
int *sum(int *v, int l) { return *v - v[l] ? v + l : sum(v + l, l); }
void down(int v) {
for (m[v] = r ^= 3, i = 2; j = i % 3 - 1 + i / 3 * W, i < 6; ++i) {
p = sum(m + v, j), k = (p - sum(m + v, -j)) / j;
*p || (p[S * r] += 1 << k), p -= k * j, *p || (p[S * r] += 1 << k);
m[v + S] = m[v + S * 2] = 0, k > 5 && (r ^= 3, r += 4, i = 8);
}
}
void ai() {
for (j = k = 0, i = S; i < 3 * S || (k = rand() % k, k || ++k, 0);)
j == m[i] && ++k, j < m[i] && (j = m[i], k = 1), ++i;
for (i = S; k && i < 3 * S || (down(i % S), 0);)m[++i] == j && --k;
}
int main() {
for (W += 2, S = W * W, m = calloc(i = S * 3, 4), srand((int)m); i--;)
i % W && -~i % W && !(i % S < W || (i + W) % S < W) || (m[i] = -1);
SetConsoleCursorInfo(GetStdHandle((DWORD)-11), &(CONSOLE_CURSOR_INFO) { 25 });
for (z = S / 2, system("cls"); r < 4 && c - 27; c = _getch() & 95) {
c - 87 || m[z - W] + 1 && (z -= W), c - 68 || m[++z] + 1 || --z;
c - 83 || m[z + W] + 1 && (z += W), c - 65 || m[--z] + 1 || ++z;
if (!c)M - 2 ? !m[z] && (down(z), r < 4 && M && (ai(), 0)) : ai();
SetConsoleCursorPosition(GetStdHandle((DWORD)-11), (COORD) { 0 });
for (i = W; i < S - W; ++i % W || _cprintf("%d\n", i / W - 1))
SetConsoleTextAttribute(GetStdHandle((DWORD)-11), i - z ? 15 : 175),
m[i] + 1 && printf(". \0○\0●" + m[i] * 3);
for (i = 1, c - 81 || ++M; ++i < W;)_cprintf(" %c", 95 + i);
M %= 3, _cprintf("\n%s|", "PvP\0PvE\0EvE" + M * 4);
_cputs(r & 1 ? "White" : "Black"), r < 4 || _cputs(" win!");
}
}
/*
操作:adsw键移动,空格下子,q键切换模式,Esc退出。
1. 模式有三种:
PvP(Player VS Player),玩家对战玩家,均由玩家自行下子
PvE(Player VS Environment),玩家对战环境,玩家下子后自动再下一子
EvE,不解释,按一下自动下一子,不受光标影响
2. '@'是白棋,'O'是黑棋(对应25行的64和79,可以自己改成自己喜欢的符号
3. 棋盘大小可以自己改(3行的W)(固定长宽比1:1)
*/
2048小游戏
#include <windows.h>
#include <conio.h>
int bg[] = {15, 240, 144, 160, 176, 192, 208, 224, 16, 32, 48, 64, 80};
int m[36] = { 0 }, score = 0, can = 0, air = 16, c = 0, i = 6, j, *p;
void move(int *q, int v) {
if (*q < 1 ? 0 : q[v] || (q[v] = *q, move(q + v, v), *q = can = 0))
q[v] - *q || (q[v] = ~*q, score += 1 << *q, *q = can = 0, ++air);
}
void order(int b, int v) { b - j && ((move(m + b, v), order(b + i, v), 0)); }
int main() {
for (p = malloc(1); i--;)m[i] = m[35 - i] = m[i * 6] = m[35 - i * 6] = -1;
for (srand(p), free(p); (air || can) && c - 27; c = _getch() & 95) {
c - 'A' && c - 'W' || (j = 30, i = 1, order(6, c - 'A' ? -6 : -1), 0);
c - 'D' && c - 'S' || (j = 6, i = -1, order(30, c - 'D' ? 6 : 1), 0);
if (!air || can || (--air, (system("cls"))))continue;
while (m[i = rand() % 30] || (m[i] = rand() % 5 ? 1 : 2, 0));
for (p = m + 30; --p - m - 6; *p < -1 && (*p = -*p));
for (; ++p - m - 31; *p + 1 && _cprintf("%5d", *p ? 1 << *p : 0))
SetConsoleTextAttribute(GetStdHandle((DWORD)-11), bg[*p % 12 + 1]),
*p + 1 && (*p ^ p[1] && *p ^ p[6] || ++can),
(p - m) % 6 || _cputs("\n");
air || can || _cputs("Game over!"), _cprintf("score:%d", score);
}
}
//ADSW使所有数字移动, 相同数字合并, 每次行动后产生新数字,
//直到无法产生移动或按下Esc键时游戏结束。
贪吃蛇
#include <windows.h>
#include <conio.h>
int main() {
int W = 20, S = W * W, * m, z[2] = { 0 }, l = 3, i, c = 'D', C, * p, f;
SetConsoleCursorInfo(GetStdHandle((DWORD)-11), &(CONSOLE_CURSOR_INFO){25});
for (srand(m = calloc(S, 4)), C = m[1] = -1; C - 27; Sleep(100)) {
if (_kbhit())C = _getch() & 95, C - 65 && C - 68 &&
C - 83 && C - 87 || (C ^ c) & 20 ^ 4 && (c = C);
p = z + !!(c & 2), * p += c / 3 & 2, * p = (-- * p + W) % W;
f = 1, * (p = m + *z + z[1] * W) > 0 && (C = 27);
for (; *p && (m[i = rand() % S] || (--m[i], ++l, --f)););
SetConsoleCursorPosition(GetStdHandle((DWORD)-11), (COORD){0});
for (i = 0, *p = l; i < S; _cputs(" "), ++i % W || _cputs("\n"))
SetConsoleTextAttribute(GetStdHandle((DWORD)-11),
m[i] > 0 ? m[i] -= f, 192 : m[i] ? 160 : 240);
}
}
//ADSW移动, 吃到食物成长, 可穿墙, 吃到自己身体或按下Esc键时游戏结束;
//可自定义蛇头位置(z[0], z[1]), 蛇长(l), 初始方向(c), 地图尺寸(W);
走迷宫
#include <stdlib.h>
#include <conio.h>
int W = 15, S, c = 81, i, j, k, *m, *L, l[4] = {1, -1};
void init(){
for (i = S; i-- || (c = m[i = rand() % S] == 2, k = 0);)
m[i] = 2 + ((i + 1) % W < 2) + (i % (S - W) < W);
for (c && (L[k++] = i); k && (j = L[i = rand() % k], 1);)
for (L[i] = L[--k], i = m[j] & 3 ? m[j] = 0 : 4; i < 4; ++i)
c = j + l[i], m[c] & 3 && ++m[c], m[c] & 3 && (L[k++] = c);
for (i = c ? W : S; i >= S ? init(), 0 : m[i - W]; i += W)
m[i] & 3 | m[S - 1 - i] & 3 || (m[j = i] = m[k = S - 1 - i] = 0);
}
int main(){
srand(m = calloc(S = W * W, 4)), L = calloc(S, 4), l[2] -= l[3] = W;
for (; c - 81 && j - k ? 0 : init(), c - 27; c = _getch() & 95){
c - 87 || m[j - W] || (j -= W), c - 68 || m[j + 1] || ++j;
c - 83 || m[j + W] || (j += W), c - 65 || m[j - 1] || --j;
for (i = system("cls"); i < S; ++i % W || _cputs("\n"))
_cputs(i - j ? m[i] ? "[]" : " " : "<>");
}
}
//ADSW移动, 按下Q键或到达另一端自动刷新, 按下Esc键时游戏结束;
//可自定义地图尺寸(W), 这个尺寸包括边界的墙
俄罗斯方块
#include <windows.h>
#include <conio.h>
#define Get(C) for (C, i = n[T]; j = X + i % 4, k = Y + i / 4 % 4, i; i >>= 4)
int W = 10, H = 25, S, i, j, k, c, d = 9, X = 0, Y = 0, T = 0, *m, n[] = {
51264, 12816, 21520, 21520, 25872, 34113, 21537, 38208, 25921, 38481,
38484, 38209, 25922, 43345, 34388, 38160, 25920, 38177, 42580, 38993};
int move(int* v, int l) {
Get (*v += l)(j < 0 || j >= W || k >= H || m[k * W + j]) && (c = 0);
return c ? 1 : (*v -= l, v == &Y && (c = -1));
}
int main() {
SetConsoleCursorInfo(GetStdHandle((DWORD)-11), &(CONSOLE_CURSOR_INFO){1});
for (srand(m = calloc(S = W * H, 4)), system("cls"); c - 27; Sleep(50)) {
Get(c = _kbhit() ? _getch() & 95 : 1) m[k * W + j] = 0;
c ^ 65 || move(&X, -1), c ^ 68 || move(&X, 1), c ^ 83 || move(&Y, 1);
c ^ 87 || (i = T < 8 ? 1 : 3, move(&T, T & i ^ i ? 1 : -i));
Get(--d || (d = 9, move(&Y, c = 1))) m[k * W + j] = T / 4 * 16 + 154;
if (c == -1 && !(Y || (c = 27), T = rand() % 20, Y = X = 0))
for (j = W, i = S - 1; j -= !!m[i], i; i-- % W || (j = W))
for (j || (k = i += W); !j && (--k >= W); m[k] = m[k - W]);
SetConsoleCursorPosition(GetStdHandle((DWORD)-11), (COORD){0});
for (; i < S; _cputs(" "), ++i % W || _cputs("\n"))
SetConsoleTextAttribute(GetStdHandle((DWORD)-11), m[i]);
}
}
//AD移动, S下坠, W旋转, 某一行填满方块则消行, 当方块堆到顶层或按下Esc键时游戏结束;
//可自定义地图尺寸(W, H)
扫雷
//简易版
#include <stdlib.h>
#include <conio.h>
int S, W = 9, H = 9, B = 10, s, p = 0, c = 1, i, *m, *M, (*f)(int, int);
int edge(int x, int y) { return x < 0 || W <= x || y < 0 || H <= y; }
void tmp(int x, int y) { edge(x, y) || m[x += W * y] - 9 && ++m[x]; }
void dig(int v, int l) {
for (l = edge(v, l) || M[v += W * l] || (++M[v], --s, m[v]) ? 0 : 9; l;)
--l - 4 || --l, f(v % W + l % 3 - 1, v / W + l / 3 - 1);
}
void set(int x, int y) {
for (f = tmp; c++ < B; m[i] = 0, dig(i % W, i / W), m[i] = 9, M[i]--)
while (m[i = rand() % S] > 8 || (abs(x - i % W) | abs(y - i / W)) < 2);
f = dig, s += B, dig(x, y);
}
int main() {
f = set, s = S = W * H, m = calloc(S * 2, 4), M = m + S, srand(m);
for ( ; B % s && !system("cls"); c = _getch() & 95, c - 27 || (B = 0)) {
c - 68 || ++p, c - 65 || --p, c - 83 || (p += W), c - 87 || (p -= W);
p = (p + S) % S, c || (f(p % W, p / W), m[p] < 9 || (B = 0));
for (i = 0; B || m[i] - 9 || ++M[i], i < S; ++i % W || _cputs("\n"))
_cprintf("%c%c", " >"[p == i], " 12345678@*"[M[i] ? m[i] : 10]);
}
_cputs(B ? "You win!" : "Game over!"), _getch();
}
//ADSW移动光标, 空格挖开对应格子, 剩余格子等于雷的数量或挖到雷或按下Esc键时游戏结束;
//可自定义地图尺寸(W, H), 雷的数量(B), 地图尺寸不要太小或太大
//完整版
#include<windows.h>
#include<stdio.h>
#include<time.h>
#define turn(x, y) (mapSize.X * (y) + (x))
#define Outside(x, y) (x < 0 || mapSize.X - 1 < x || y < 0 || mapSize.Y - 1 < y)
int *map, *mark, count, bomb, firstOpen, game, bombCount, baginTime;
int node[8][2] = { 1,0,-1,0,0,1,0,-1,-1,-1,-1,1,1,-1,1,1 };
char *num[10] = { " ", "①", "②", "③", "④", "⑤", "⑥", "⑦", "⑧", "●" };
COORD size = { 18,11 }, origin = { 0,0 }, mapSize = { 0,0 }, pos = { 0,0 };
HANDLE hOut, hIn;
INPUT_RECORD Buf;
int *color[10] = { 0,11,10,12,14,1,2,6,4,4 };
//光标定位
void gotoxy(int x,int y)
{
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(hOut, pos);
}
//设置窗口大小
void setScreenSize(int lines, int cols)
{
COORD size = { lines,cols };
SMALL_RECT rect = { 0,0,size.X - 1,size.Y - 1 };
SetConsoleWindowInfo(hOut, 1, &rect);
SetConsoleScreenBufferSize(hOut, size);
SetConsoleWindowInfo(hOut, 1, &rect);
}
//隐藏光标
void hideCursor()
{
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(hOut, &CursorInfo);
CursorInfo.bVisible = 0;
SetConsoleCursorInfo(hOut, &CursorInfo);
}
//精准延时
void delay(int ms)
{
static clock_t oldtime = 0;
while (clock() - ms < oldtime)
Sleep(1);
oldtime = clock();
}
//翻开一个位置
void open(int x,int y)
{
if (Outside(x,y))return;
if (!mark[turn(x,y)])return;
mark[turn(x, y)] = 0;
gotoxy(x * 2, y);
SetConsoleTextAttribute(hOut, color[map[turn(x, y)]]);
printf(num[map[turn(x, y)]]);
count--;
if (map[turn(x, y)] > 0)return;
for (int i = 0; i < 8; i++)
open(x + node[i][0], y + node[i][1]);
}
//标记一个位置
void sign(int x, int y)
{
if (Outside(x, y))return;
int *temp = &mark[turn(x, y)];
if (!*temp)return;
gotoxy(x * 2, y);
if (*temp == 1)
{
*temp = 2;
SetConsoleTextAttribute(hOut, 4);
printf("★");
bombCount--;
}
else
{
*temp = 1;
SetConsoleTextAttribute(hOut, 15);
printf("■");
bombCount++;
}
}
//设置炸弹
void setBomb(int x, int y)
{
for (int i = 0,j,k; i < bomb;)
{
j = rand() % mapSize.X, k = rand() % mapSize.Y;
if ((-2 < x - j && x - j < 2) && (-2 < y - k && y - k < 2))continue;
if (map[turn(j, k)] == 9)continue;
map[turn(j, k)] = 9, i++;
for (int i = 0,m,n; i < 8; i++)
{
m = j + node[i][0], n = k + node[i][1];
if (!Outside(m, n) && map[turn(m, n)] - 9)map[turn(m, n)]++;
}
}
}
//展开
void fun(int x,int y)
{
int num = 0;
for (int i = 0,j,k; i < 8; i++)
{
j = x + node[i][0], k = y + node[i][1];
if (!Outside(j, k) && mark[turn(j, k)] == 2)num++;
}
if (map[turn(x, y)] == num)
{
for (int i = 0,j,k; i < 8; i++)
{
j = x + node[i][0], k = y + node[i][1];
if (Outside(j, k) || mark[turn(j, k)] - 1)continue;
if (open(j, k), map[turn(j, k)] == 9)game = 0;
}
}
}
int main()
{
int Result, i = 0, fps = 10;
hIn = GetStdHandle(STD_INPUT_HANDLE);
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
hideCursor();
back:;
setScreenSize(18, 11);
FillConsoleOutputCharacter(hOut, ' ', (size.X - 1)*(size.Y + 1), origin, &i);
SetConsoleCursorPosition(hOut, origin);
SetConsoleTextAttribute(hOut, 15), printf(" Minesweeper! \n\n");
SetConsoleTextAttribute(hOut, 10), printf(" Easy \n");
SetConsoleTextAttribute(hOut, 14), printf(" Medium \n");
SetConsoleTextAttribute(hOut, 13), printf(" Hard \n");
SetConsoleTextAttribute(hOut, 12), printf(" Custom \n\n\n");
SetConsoleTextAttribute(hOut, 11), printf(" by:RainbowRoad1");
SetConsoleTextAttribute(hOut, 15);
while (1)
{
ReadConsoleInput(hIn, &Buf, 1, &Result);
pos = Buf.Event.MouseEvent.dwMousePosition;
if (Buf.Event.MouseEvent.dwButtonState)
{
if (pos.Y == 2)mapSize.X = mapSize.Y = 9, bomb = 10;
else if (pos.Y == 3)mapSize.X = mapSize.Y = 16, bomb = 40;
else if (pos.Y == 4)mapSize.X = 30, mapSize.Y = 16, bomb = 99;
else if (pos.Y == 5)
{
gotoxy(0, 6);
printf("input:");
scanf_s("%d,%d,%d", &mapSize.X, &mapSize.Y, &bomb);
num[0] = " ";
}
else continue;
break;
}
if (GetAsyncKeyState(' ') & 0x8000)exit(0);
}
size.X = mapSize.X * 2, size.Y = mapSize.Y + 2;
setScreenSize(size.X, size.Y);
Sleep(100);
FlushConsoleInputBuffer(hIn);
restart:;
srand((unsigned)time(0));
if (map)free(map);
if (mark)free(mark);
map = (int*)calloc(mapSize.X*mapSize.Y, sizeof(int));
mark = (int*)calloc(mapSize.X*mapSize.Y, sizeof(int));
count = mapSize.X*mapSize.Y, bombCount = bomb;
firstOpen = 1, game = 1, baginTime = clock();
SetConsoleTextAttribute(hOut, 15);
SetConsoleCursorPosition(hOut, origin);
for (i = 0; i < mapSize.X*mapSize.Y;i++)printf("■");
for (i = 0; i < mapSize.X*mapSize.Y; i++)mark[i] = 1;
gotoxy(mapSize.X * 2 - 7, mapSize.Y);
printf("restart");
gotoxy(mapSize.X * 2 - 5, mapSize.Y + 1);
printf("back");
while (1)
{
if (GetNumberOfConsoleInputEvents(hIn, &i));
if (i)
{
while (i--)
{
ReadConsoleInput(hIn, &Buf, 1, &Result);
pos = Buf.Event.MouseEvent.dwMousePosition;
if (Buf.Event.MouseEvent.dwButtonState)
{
pos.X = pos.X / 2;
switch (Buf.Event.MouseEvent.dwButtonState)
{
case FROM_LEFT_1ST_BUTTON_PRESSED:
if (firstOpen)setBomb(pos.X, pos.Y), firstOpen = 0;
open(pos.X, pos.Y);
if (map[turn(pos.X, pos.Y)] == 9)game = 0;
if (pos.Y == mapSize.Y)goto restart;
if (pos.Y == mapSize.Y + 1)goto back;
break;
case RIGHTMOST_BUTTON_PRESSED:
if (!Outside(pos.X, pos.Y))sign(pos.X, pos.Y); break;
case FROM_LEFT_2ND_BUTTON_PRESSED:
if (!Outside(pos.X, pos.Y))fun(pos.X, pos.Y); break;
}
}
}
}
gotoxy(0, mapSize.Y);
SetConsoleTextAttribute(hOut, 1);
if (count <= bomb && printf("\nyou win! "))break;
if (!game)
{
printf("\nGame over! ");
SetConsoleTextAttribute(hOut, 4);
for (i=0; i < mapSize.X*mapSize.Y; i++)
if (map[i] == 9 && mark[i])
{
gotoxy(i%mapSize.X * 2, i / mapSize.X);
printf("●");
}
break;
}
SetConsoleTextAttribute(hOut, 15);
printf("time:%-5d\nresidue:%-5d", (clock() - baginTime) / 1000, bombCount);
delay(1000 / fps);
}
while (1)
{
ReadConsoleInput(hIn, &Buf, 1, &Result);
pos = Buf.Event.MouseEvent.dwMousePosition;
if (Buf.Event.MouseEvent.dwButtonState)
{
if (pos.Y == mapSize.Y)goto restart;
if (pos.Y == mapSize.Y + 1)goto back;
}
if (GetAsyncKeyState(' ') & 0x8000)break;
Sleep(1000 / fps);
}
}
//交互更加友好: 鼠标左键点击, 右键标记, 中键展开
//增加一个难度选择的主菜单, 可自定义难度
//界面更加直观, 有剩余雷数和用时显示
//游戏时增加了重置和返回菜单的选项