A turn-based multiplayer Memory Game built with ASP.NET Core MVC and SQL Server as part of the course
📘 Databasteknik och webbaserade system at IT-Högskolan Sverige AB.
MemoryGame is a web-based multiplayer game where two players take turns flipping cards to find matching pairs.
The project demonstrates the use of relational databases, MVC architecture, CRUD operations, and session handling in a full-stack ASP.NET web application.
This was an individual school project that I designed and implemented end-to-end. Everything in this repository was written by me.
What I built:
- Database schema – designed from scratch: six normalized tables with composite foreign keys that enforce referential integrity at the DB level (e.g. a
Move's tiles must belong to the sameGamerow). - Custom Repository layer using raw ADO.NET – no Entity Framework; all queries are hand-written parameterized SQL, which was a course requirement to demonstrate direct SQL knowledge.
- Session-based authentication – including PBKDF2-SHA256 password hashing with a random salt (
Security/PasswordHasher.cs), without relying on ASP.NET Identity. - Real-time turn polling – the game board auto-refreshes via AJAX so each player sees the opponent's last move without a full page reload.
- Lobby system – Player A creates a game, Player B joins, and the game transitions automatically through
Waiting → InProgress → Completed. - Card Admin CRUD interface – full create/read/update/delete for the card catalogue.
- Azure deployment via Visual Studio's publish wizard.
What I learned:
- Writing safe, parameterized ADO.NET queries without an ORM safety net.
- Designing a turn-based state machine enforced by a SQL
CHECKconstraint. - Managing sessions in ASP.NET Core without the Identity middleware stack.
- Structuring an MVC application with Dependency Injection for testability.
✅ Two-player turn-based gameplay
✅ Login system with sessions
✅ Lobby where users can create, join, or delete games
✅ Real-time updates through AJAX polling
✅ Card Admin CRUD interface (Create / Read / Update / Delete)
✅ SQL database integration for all game entities
✅ Clean Bootstrap 5 interface
✅ Session-based authentication
| Layer | Technology |
|---|---|
| Frontend | HTML5, CSS3, Bootstrap 5, Razor Views |
| Backend | ASP.NET Core MVC (C#) |
| Database | Microsoft SQL Server |
| Data Access | Custom Repository Layer (ADO.NET) |
| Authentication | Session-based login |
| Version Control | Git & GitHub |
Browser (Razor Views + jQuery AJAX)
│
▼
┌───────────────────────────────────────┐
│ Controllers │
│ AccountController · GameController │
│ CardAdminController · HomeController │
└────────────────┬──────────────────────┘
│ constructor-injected interfaces
▼
┌───────────────────────────────────────┐
│ Repositories (ADO.NET) │
│ UserRepository · GameRepository │
│ CardRepository · TileRepository │
│ MoveRepository │
└────────────────┬──────────────────────┘
│ SqlConnection via IDbConnectionFactory
▼
┌───────────────────────────────────────┐
│ SQL Server │
│ Tables: User · Game · GamePlayer │
│ Card · Tile · Move │
└───────────────────────────────────────┘
Session cookies hold the logged-in UserID and Username. No Entity Framework — all queries are hand-written parameterized SQL.
- .NET 8 SDK
- SQL Server (any edition), SQL Server Express, or LocalDB (ships with Visual Studio)
- SQL Server Management Studio (SSMS) or Azure Data Studio (optional)
git clone https://github.com/sam-razavi/memorygame.git
cd memorygameOpen your SQL client and run:
CREATE DATABASE MemoryGameDb;Then open MemoryGame/Database/01_CreateSchema.sql and execute it against MemoryGameDb.
The script drops and recreates all tables, so it is safe to re-run.
Copy the example file:
cp MemoryGame/appsettings.example.json MemoryGame/appsettings.jsonThen edit appsettings.json and replace the MemoryGameDb value with your connection string:
| Scenario | Connection string |
|---|---|
| LocalDB (Visual Studio default) | Server=(localdb)\\MSSQLLocalDB;Database=MemoryGameDb;Trusted_Connection=True;MultipleActiveResultSets=true |
| SQL Server Express | Server=.\\SQLEXPRESS;Database=MemoryGameDb;Trusted_Connection=True;MultipleActiveResultSets=true |
| Named instance | Server=YOUR_PC\\INSTANCE;Database=MemoryGameDb;Trusted_Connection=True;MultipleActiveResultSets=true |
| SQL auth | Server=YOUR_SERVER;Database=MemoryGameDb;User Id=sa;Password=YOUR_PASSWORD;MultipleActiveResultSets=true |
Note:
appsettings.jsonis listed in.gitignoreto keep credentials out of source control.
appsettings.example.jsonshows the required keys without real values.
cd MemoryGame
dotnet runThe terminal prints the local URL (e.g. http://localhost:5013).
Open it in your browser, register two accounts (use a second browser window or incognito), and start a game.
cd MemoryGame.Tests
dotnet testThe MemoryGame.Tests project contains unit tests that run without a database connection.
| Test class | What it covers |
|---|---|
PasswordHasherTests |
Hash format, verify correct password, reject wrong password, reject malformed stored string, unique salts per call |
GameModelTests |
Default Status value, nullable defaults, property assignment for Game, Card, and Tile |
dotnet test MemoryGame.TestsThese tests cover the pure-logic classes (PasswordHasher, model POCOs) that have no external dependencies. Integration tests against a live database are a natural next step.
- Player A creates a new game in the lobby.
- Player B joins the same game.
- The game starts automatically; players alternate flipping two tiles per turn.
- Matching pairs score a point; a miss passes the turn to the opponent.
- When all tiles are matched, the system determines the winner automatically.
Players can create, join, or manage games from the lobby.
Watch a full turn: flipping tiles, finding matches, and tracking scores.
Flip cards to find matching pairs — matched tiles turn green!
Final scoreboard with winner announcement and full move history.
https://memorygame-sam-b4dbbha5anguhxbt.germanywestcentral-01.azurewebsites.net/



