Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e9814dea3e | ||
2855b64f03 | |||
9c45259962 | |||
b1256014e3 | |||
b1af7b4f41 | |||
2b0f20d65a | |||
e394d0986e | |||
d8eb655dd7 | |||
b878c2ddb3 | |||
a0e5850e68 | |||
84972ed9bb | |||
08f6ee7161 | |||
f7d2f138ea | |||
1d07cee01a |
3
.gitignore
vendored
3
.gitignore
vendored
@ -5,5 +5,4 @@
|
||||
lib
|
||||
.vscode
|
||||
bin
|
||||
build
|
||||
Makefile
|
||||
build
|
@ -9,7 +9,7 @@ DBG_CXXFLAGS := $(CXXFLAGS) -g
|
||||
RLS_CXXFLAGS := $(CXXFLAGS) -O2
|
||||
|
||||
# linker stuff
|
||||
LDFLAGS := -lncursesw
|
||||
LDFLAGS := -lncursesw -lSDL2
|
||||
DBG_LDFLAGS := $(LDFLAGS)
|
||||
RLS_LDFLAGS := $(LDFLAGS) -s
|
||||
|
||||
@ -39,7 +39,7 @@ $(shell mkdir -p $(RLS_DIR))
|
||||
$(shell mkdir -p $(BUILD_DIR))
|
||||
|
||||
# phony rules
|
||||
.PHONY := all debug release clean install uninstall
|
||||
.PHONY = all debug release clean install uninstall
|
||||
|
||||
all: release
|
||||
|
72
Makefile.win
72
Makefile.win
@ -1,72 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2025 thorium1256
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# compiler stuff
|
||||
CXX := c++
|
||||
CXXFLAGS := -I include -std=c++11 -Wall -Wextra
|
||||
DBG_CXXFLAGS := $(CXXFLAGS) -g
|
||||
RLS_CXXFLAGS := $(CXXFLAGS) -O2
|
||||
|
||||
# linker stuff
|
||||
LDFLAGS := -L C:\msys64\mingw64\bin -lncursesw6
|
||||
DBG_LDFLAGS := $(LDFLAGS)
|
||||
RLS_STRP_LDFLAGS := $(LDFLAGS) -s
|
||||
|
||||
# directories
|
||||
BUILD_DIR := build
|
||||
SRC_DIR := src
|
||||
BIN_DIR := bin
|
||||
DBG_DIR := $(BIN_DIR)\debug
|
||||
RLS_DIR := $(BIN_DIR)\release
|
||||
LIB_DIR := lib
|
||||
DBG_EXEC := $(DBG_DIR)\debug.exe
|
||||
RLS_STRIPPED_EXEC := $(RLS_DIR)\tuimine.exe
|
||||
|
||||
# sources and objects
|
||||
LIBS := $(wildcard $(LIB_DIR)/*.dll)
|
||||
LIBS_DBG := $(patsubst $(LIB_DIR)/%.dll, $(DBG_DIR)\\%.dll, $(LIBS))
|
||||
LIBS_RLS := $(patsubst $(LIB_DIR)/%.dll, $(RLS_DIR)\\%.dll, $(LIBS))
|
||||
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
|
||||
DBG_OBJS := $(patsubst $(SRC_DIR)/%.cpp,$(BUILD_DIR)/debug_%.o,$(SRCS))
|
||||
RLS_OBJS := $(patsubst $(SRC_DIR)/%.cpp,$(BUILD_DIR)/release_%.o,$(SRCS))
|
||||
|
||||
$(shell if not exist $(BIN_DIR) mkdir $(BIN_DIR))
|
||||
$(shell if not exist $(DBG_DIR) mkdir $(DBG_DIR))
|
||||
$(shell if not exist $(RLS_DIR) mkdir $(RLS_DIR))
|
||||
$(shell if not exist $(BUILD_DIR) mkdir $(BUILD_DIR))
|
||||
|
||||
# phony rules
|
||||
.PHONY := all debug release clean libraries_debug libraries_release both
|
||||
|
||||
all: release
|
||||
|
||||
debug: $(DBG_EXEC) libraries_debug
|
||||
release: $(RLS_STRIPPED_EXEC) libraries_release
|
||||
both: debug release
|
||||
|
||||
libraries_debug: $(LIBS_DBG)
|
||||
libraries_release: $(LIBS_RLS)
|
||||
|
||||
# linking
|
||||
$(DBG_EXEC): $(DBG_OBJS)
|
||||
$(CXX) -o $@ $^ $(DBG_LDFLAGS)
|
||||
|
||||
$(RLS_STRIPPED_EXEC): $(RLS_OBJS)
|
||||
$(CXX) -o $@ $^ $(RLS_STRP_LDFLAGS)
|
||||
|
||||
# compiling
|
||||
$(BUILD_DIR)/debug_%.o: $(SRC_DIR)/%.cpp
|
||||
$(CXX) -c -o $@ $< $(DBG_CXXFLAGS)
|
||||
|
||||
$(BUILD_DIR)/release_%.o: $(SRC_DIR)/%.cpp
|
||||
$(CXX) -c -o $@ $< $(RLS_CXXFLAGS)
|
||||
|
||||
$(DBG_DIR)\\%.dll: $(LIB_DIR)\\%.dll
|
||||
xcopy $< $(DBG_DIR)\ >nul
|
||||
|
||||
$(RLS_DIR)\\%.dll: $(LIB_DIR)\\%.dll
|
||||
xcopy $< $(RLS_DIR)\ >nul
|
||||
|
||||
clean:
|
||||
rmdir /s /q $(BUILD_DIR) $(DBG_DIR) $(RLS_DIR)
|
341
src/main.cpp
341
src/main.cpp
@ -4,9 +4,10 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <ncursesw/ncurses.h>
|
||||
#include <ncurses.h>
|
||||
#include <ctime>
|
||||
#include <unistd.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include "Board.h"
|
||||
#ifndef _WIN32
|
||||
#include <signal.h>
|
||||
@ -20,6 +21,8 @@ void handleSIGWINCH(int sig)
|
||||
|
||||
#define MAX_TIME 60
|
||||
|
||||
SDL_GameController *controller;
|
||||
|
||||
void startGame(Board &board)
|
||||
{
|
||||
int minesLeft = board.getMineCount();
|
||||
@ -44,10 +47,11 @@ void startGame(Board &board)
|
||||
{
|
||||
usleep((1000 / MAX_TIME) * 1000);
|
||||
#ifndef _WIN32
|
||||
if((w.ws_row < boardSize.x + 3 )||( w.ws_col < boardSize.y + 2)) {
|
||||
mvprintw(w.ws_col/2, w.ws_row/2, "Your terminal is too small:");
|
||||
mvprintw(w.ws_col / 2 + 1, w.ws_row/2, "Current size: %dx%d", w.ws_row, w.ws_col);
|
||||
mvprintw(w.ws_col / 2 + 2, w.ws_row/2, "Min size: %dx%d", boardSize.x + 3, boardSize.y + 2);
|
||||
if ((w.ws_row < boardSize.x + 3) || (w.ws_col < boardSize.y + 2))
|
||||
{
|
||||
mvprintw(w.ws_col / 2, w.ws_row / 2, "Your terminal is too small:");
|
||||
mvprintw(w.ws_col / 2 + 1, w.ws_row / 2, "Current size: %dx%d", w.ws_row, w.ws_col);
|
||||
mvprintw(w.ws_col / 2 + 2, w.ws_row / 2, "Min size: %dx%d", boardSize.x + 3, boardSize.y + 2);
|
||||
refresh();
|
||||
continue;
|
||||
}
|
||||
@ -160,99 +164,207 @@ void startGame(Board &board)
|
||||
|
||||
c = getch();
|
||||
if (c == ERR)
|
||||
continue;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case KEY_UP:
|
||||
cursorY = (cursorY > 0) ? cursorY - 1 : boardSize.y - 1;
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
cursorY = (cursorY < boardSize.y - 1) ? cursorY + 1 : 0;
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
cursorX = (cursorX > 0) ? cursorX - 1 : boardSize.x - 1;
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
cursorX = (cursorX < boardSize.x - 1) ? cursorX + 1 : 0;
|
||||
break;
|
||||
case 'q':
|
||||
exit(0);
|
||||
echo();
|
||||
cbreak();
|
||||
endwin();
|
||||
break;
|
||||
case 'z':
|
||||
if (!somethingHasBeenDone)
|
||||
if (controller != nullptr)
|
||||
{
|
||||
startTime = time(nullptr);
|
||||
somethingHasBeenDone = true;
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
if (event.type == SDL_CONTROLLERBUTTONDOWN)
|
||||
{
|
||||
switch (event.cbutton.button)
|
||||
{
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_UP:
|
||||
cursorY = (cursorY > 0) ? cursorY - 1 : boardSize.y - 1;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
|
||||
cursorY = (cursorY < boardSize.y - 1) ? cursorY + 1 : 0;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
|
||||
cursorX = (cursorX > 0) ? cursorX - 1 : boardSize.x - 1;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
|
||||
cursorX = (cursorX < boardSize.x - 1) ? cursorX + 1 : 0;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_START:
|
||||
if (isPaused)
|
||||
{
|
||||
pauseTime = difftime(time(NULL), startPauseTime);
|
||||
totalpausetime += pauseTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
startPauseTime = time(NULL);
|
||||
}
|
||||
isPaused = !isPaused;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_A:
|
||||
if (!somethingHasBeenDone)
|
||||
{
|
||||
startTime = time(nullptr);
|
||||
somethingHasBeenDone = true;
|
||||
}
|
||||
if (board.getCellStateAt(cursorX, cursorY) == Cell::State::Revealed)
|
||||
{
|
||||
if (!somethingHasBeenDone)
|
||||
{
|
||||
startTime = time(nullptr);
|
||||
somethingHasBeenDone = true;
|
||||
}
|
||||
auto neighbors = board.getNeighborsOf(cursorX, cursorY);
|
||||
int flagCount = 0;
|
||||
for (const Cell &neighbor : neighbors)
|
||||
{
|
||||
if (neighbor.getState() == Cell::State::Flagged)
|
||||
flagCount++;
|
||||
}
|
||||
if (static_cast<int>(board.revealCellAt(cursorX, cursorY).getContent()) > flagCount)
|
||||
break;
|
||||
for (const Cell &neighbor : neighbors)
|
||||
{
|
||||
if (neighbor.getState() == Cell::State::Flagged)
|
||||
continue;
|
||||
board.revealCellAt(neighbor.getPosition().x, neighbor.getPosition().y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
board.revealCellAt(cursorX, cursorY);
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_B:
|
||||
if (board.getCellStateAt(cursorX, cursorY) == Cell::State::Revealed)
|
||||
break;
|
||||
if (!somethingHasBeenDone)
|
||||
{
|
||||
startTime = time(nullptr);
|
||||
somethingHasBeenDone = true;
|
||||
}
|
||||
if (board.getCellStateAt(cursorX, cursorY) == Cell::State::Flagged)
|
||||
{
|
||||
minesLeft++;
|
||||
}
|
||||
else
|
||||
{
|
||||
minesLeft--;
|
||||
}
|
||||
board.flagCellAt(cursorX, cursorY);
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_MISC1:
|
||||
startTime = time(NULL);
|
||||
minesLeft = board.getMineCount();
|
||||
board.regenerateBoard();
|
||||
somethingHasBeenDone = false;
|
||||
elapsedTime = 0;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_BACK:
|
||||
echo();
|
||||
cbreak();
|
||||
endwin();
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
board.revealCellAt(cursorX, cursorY);
|
||||
break;
|
||||
case 'x':
|
||||
if (board.getCellStateAt(cursorX, cursorY) == Cell::State::Revealed)
|
||||
}
|
||||
|
||||
if (!(c == ERR))
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case KEY_UP:
|
||||
cursorY = (cursorY > 0) ? cursorY - 1 : boardSize.y - 1;
|
||||
break;
|
||||
if (!somethingHasBeenDone)
|
||||
{
|
||||
startTime = time(nullptr);
|
||||
somethingHasBeenDone = true;
|
||||
}
|
||||
if (board.getCellStateAt(cursorX, cursorY) == Cell::State::Flagged)
|
||||
{
|
||||
minesLeft++;
|
||||
}
|
||||
else
|
||||
{
|
||||
minesLeft--;
|
||||
}
|
||||
board.flagCellAt(cursorX, cursorY);
|
||||
break;
|
||||
case 'r':
|
||||
startTime = time(NULL);
|
||||
minesLeft = board.getMineCount();
|
||||
board.regenerateBoard();
|
||||
somethingHasBeenDone = false;
|
||||
elapsedTime = 0;
|
||||
break;
|
||||
case 'p':
|
||||
if (isPaused)
|
||||
{
|
||||
pauseTime = difftime(time(NULL), startPauseTime);
|
||||
totalpausetime += pauseTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
startPauseTime = time(NULL);
|
||||
}
|
||||
isPaused = !isPaused;
|
||||
break;
|
||||
case 'c':
|
||||
if (board.getCellStateAt(cursorX, cursorY) != Cell::State::Revealed)
|
||||
{
|
||||
case KEY_DOWN:
|
||||
cursorY = (cursorY < boardSize.y - 1) ? cursorY + 1 : 0;
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
cursorX = (cursorX > 0) ? cursorX - 1 : boardSize.x - 1;
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
cursorX = (cursorX < boardSize.x - 1) ? cursorX + 1 : 0;
|
||||
break;
|
||||
case 'q':
|
||||
echo();
|
||||
cbreak();
|
||||
endwin();
|
||||
exit(0);
|
||||
break;
|
||||
case 'z':
|
||||
if (!somethingHasBeenDone)
|
||||
{
|
||||
startTime = time(nullptr);
|
||||
somethingHasBeenDone = true;
|
||||
}
|
||||
board.revealCellAt(cursorX, cursorY);
|
||||
break;
|
||||
case 'x':
|
||||
if (board.getCellStateAt(cursorX, cursorY) == Cell::State::Revealed)
|
||||
break;
|
||||
if (!somethingHasBeenDone)
|
||||
{
|
||||
startTime = time(nullptr);
|
||||
somethingHasBeenDone = true;
|
||||
}
|
||||
if (board.getCellStateAt(cursorX, cursorY) == Cell::State::Flagged)
|
||||
{
|
||||
minesLeft++;
|
||||
}
|
||||
else
|
||||
{
|
||||
minesLeft--;
|
||||
}
|
||||
board.flagCellAt(cursorX, cursorY);
|
||||
break;
|
||||
case 'r':
|
||||
startTime = time(NULL);
|
||||
minesLeft = board.getMineCount();
|
||||
board.regenerateBoard();
|
||||
somethingHasBeenDone = false;
|
||||
elapsedTime = 0;
|
||||
break;
|
||||
case 'p':
|
||||
if (isPaused)
|
||||
{
|
||||
pauseTime = difftime(time(NULL), startPauseTime);
|
||||
totalpausetime += pauseTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
startPauseTime = time(NULL);
|
||||
}
|
||||
isPaused = !isPaused;
|
||||
break;
|
||||
case 'c':
|
||||
if (board.getCellStateAt(cursorX, cursorY) != Cell::State::Revealed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (!somethingHasBeenDone)
|
||||
{
|
||||
startTime = time(nullptr);
|
||||
somethingHasBeenDone = true;
|
||||
}
|
||||
auto neighbors = board.getNeighborsOf(cursorX, cursorY);
|
||||
int flagCount = 0;
|
||||
for (const Cell &neighbor : neighbors)
|
||||
{
|
||||
if (neighbor.getState() == Cell::State::Flagged)
|
||||
flagCount++;
|
||||
}
|
||||
if (static_cast<int>(board.revealCellAt(cursorX, cursorY).getContent()) > flagCount)
|
||||
break;
|
||||
for (const Cell &neighbor : neighbors)
|
||||
{
|
||||
if (neighbor.getState() == Cell::State::Flagged)
|
||||
continue;
|
||||
board.revealCellAt(neighbor.getPosition().x, neighbor.getPosition().y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!somethingHasBeenDone)
|
||||
{
|
||||
startTime = time(nullptr);
|
||||
somethingHasBeenDone = true;
|
||||
}
|
||||
auto neighbors = board.getNeighborsOf(cursorX, cursorY);
|
||||
int flagCount = 0;
|
||||
for (const Cell &neighbor : neighbors)
|
||||
{
|
||||
if (neighbor.getState() == Cell::State::Flagged)
|
||||
flagCount++;
|
||||
}
|
||||
if (static_cast<int>(board.revealCellAt(cursorX, cursorY).getContent()) > flagCount)
|
||||
break;
|
||||
for (const Cell &neighbor : neighbors)
|
||||
{
|
||||
if (neighbor.getState() == Cell::State::Flagged)
|
||||
continue;
|
||||
board.revealCellAt(neighbor.getPosition().x, neighbor.getPosition().y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (isPaused)
|
||||
@ -282,11 +394,13 @@ void startGame(Board &board)
|
||||
{
|
||||
Board newBoard(boardSize.x, boardSize.y, board.getMineCount());
|
||||
startGame(newBoard);
|
||||
} else if(c == 'q') {
|
||||
exit(0);
|
||||
}
|
||||
else if (c == 'q')
|
||||
{
|
||||
echo();
|
||||
cbreak();
|
||||
endwin();
|
||||
exit(0);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -312,26 +426,61 @@ void startGame(Board &board)
|
||||
{
|
||||
Board newBoard(boardSize.x, boardSize.y, board.getMineCount());
|
||||
startGame(newBoard);
|
||||
} else if(c == 'q') {
|
||||
exit(0);
|
||||
}
|
||||
else if (c == 'q')
|
||||
{
|
||||
echo();
|
||||
cbreak();
|
||||
endwin();
|
||||
exit(0);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
SDL_GameController *findController()
|
||||
{
|
||||
for (int i = 0; i < SDL_NumJoysticks(); i++)
|
||||
{
|
||||
if (SDL_IsGameController(i))
|
||||
{
|
||||
return SDL_GameControllerOpen(i);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
signal(SIGWINCH, handleSIGWINCH);
|
||||
#endif
|
||||
setlocale(LC_ALL, "");
|
||||
initscr();
|
||||
noecho();
|
||||
cbreak();
|
||||
keypad(stdscr, TRUE);
|
||||
nodelay(stdscr, TRUE);
|
||||
#ifndef _WIN32
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
#endif
|
||||
|
||||
bool controllerSupport;
|
||||
|
||||
if (SDL_Init(SDL_INIT_GAMECONTROLLER) < 0)
|
||||
{
|
||||
std::cerr << "SDL failed to initialize GameController API! Controller support will not be available!" << std::endl;
|
||||
controllerSupport = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
controllerSupport = true;
|
||||
}
|
||||
|
||||
controller = findController();
|
||||
if (controller != nullptr)
|
||||
controllerSupport = false; // no controller for you
|
||||
|
||||
start_color();
|
||||
init_pair(1, COLOR_BLUE, COLOR_BLACK);
|
||||
|
Loading…
x
Reference in New Issue
Block a user