add tic tac toe game
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
apatil 2025-05-06 00:01:01 +01:00
parent 0e47ca2572
commit 38f9c8d7e3
6 changed files with 135 additions and 13 deletions

View File

@ -1,4 +1,4 @@
import { Box, Typography } from '@mui/material'; import { Box, Container, Typography } from '@mui/material';
import { getPostBySlug, getAllSlugs } from '../../../lib/posts'; import { getPostBySlug, getAllSlugs } from '../../../lib/posts';
import { notFound } from 'next/navigation'; import { notFound } from 'next/navigation';
@ -13,10 +13,10 @@ export default async function BlogPost({ params }: Props) {
const post = await getPostBySlug(slug); const post = await getPostBySlug(slug);
if (!post) return notFound(); if (!post) return notFound();
return ( return (
<Box component={'article'}> <Container component={'article'}>
<Typography variant='h2'>{post.title}</Typography> <Typography variant='h2'>{post.title}</Typography>
<Typography variant='body2'>{post.date}</Typography> <Typography variant='body2'>{post.date}</Typography>
<Box dangerouslySetInnerHTML={{ __html: post.contentHtml }} /> <Box dangerouslySetInnerHTML={{ __html: post.contentHtml }} />
</Box> </Container>
); );
} }

View File

@ -1,10 +1,10 @@
import { getAllPosts } from '../../lib/posts'; import { getAllPosts } from '../../lib/posts';
import ArticleIcon from '@mui/icons-material/Article'; import ArticleIcon from '@mui/icons-material/Article';
import { Avatar, Box, Link, List, ListItem, ListItemAvatar, ListItemButton, ListItemText, Typography } from '@mui/material'; import { Avatar, Container, Link, List, ListItem, ListItemAvatar, ListItemButton, ListItemText, Typography } from '@mui/material';
export default function Home() { export default function Home() {
const posts = getAllPosts(); const posts = getAllPosts();
return ( return (
<Box> <Container>
<Typography variant='h1' >My Blog</Typography> <Typography variant='h1' >My Blog</Typography>
<List> <List>
{posts.map(post => ( {posts.map(post => (
@ -20,6 +20,6 @@ export default function Home() {
</ListItem> </ListItem>
))} ))}
</List> </List>
</Box > </Container >
); );
} }

View File

@ -1,11 +1,12 @@
import { Box, Typography } from "@mui/material"; import Xo from "@/components/Xo/Xo";
import { Container } from "@mui/material";
export default function Home() { export default function Home() {
return ( return (
<Box> <Container>
<Typography variant={'h1'}>Welcome to the den</Typography>
<Typography variant="body1">Here lives the geek bear who is hungry for bits and bytes. Ravaging through the internet dumpster finding the finest 0s and 1s. He looks for speed and performance</Typography> <Xo />
</Box> </Container>
); );
} }

View File

@ -47,14 +47,13 @@ export default function Header() {
<Toolbar> <Toolbar>
<IconButton <IconButton
size='large' size='large'
sx={{ color: 'background.paper' }}
aria-label="open drawer" aria-label="open drawer"
edge="start" edge="start"
onClick={handleDrawerToggle} onClick={handleDrawerToggle}
> >
<MenuIcon /> <MenuIcon />
</IconButton> </IconButton>
<Typography variant="h6" padding={2} color='background.paper'> <Typography variant="h4" padding={2}>
TCG TCG
</Typography> </Typography>
<Box sx={{ flexGrow: 1 }} /> <Box sx={{ flexGrow: 1 }} />

121
src/components/Xo/Xo.tsx Normal file
View File

@ -0,0 +1,121 @@
'use client'
import { useEffect, useState } from 'react';
import {
Container,
Typography,
Grid,
Paper,
Button,
Box,
} from '@mui/material';
type Player = 'X' | 'O';
type Cell = Player | null;
const emptyBoard: Cell[] = Array(9).fill(null);
const winningCombos = [
[0, 1, 2], [3, 4, 5], [6, 7, 8],
[0, 3, 6], [1, 4, 7], [2, 5, 8],
[0, 4, 8], [2, 4, 6],
];
function checkWinner(board: Cell[]): Player | 'Draw' | null {
for (const [a, b, c] of winningCombos) {
if (board[a] && board[a] === board[b] && board[a] === board[c]) {
return board[a];
}
}
return board.includes(null) ? null : 'Draw';
}
function minimax(board: Cell[], isMaximizing: boolean): { score: number; index: number } {
const winner = checkWinner(board);
if (winner === 'O') return { score: 1, index: -1 };
if (winner === 'X') return { score: -1, index: -1 };
if (winner === 'Draw') return { score: 0, index: -1 };
let bestMove = -1;
let bestScore = isMaximizing ? -Infinity : Infinity;
for (let i = 0; i < board.length; i++) {
if (board[i] === null) {
board[i] = isMaximizing ? 'O' : 'X';
const result = minimax(board, !isMaximizing);
board[i] = null;
if (isMaximizing) {
if (result.score > bestScore) {
bestScore = result.score;
bestMove = i;
}
} else {
if (result.score < bestScore) {
bestScore = result.score;
bestMove = i;
}
}
}
}
return { score: bestScore, index: bestMove };
}
export default function XOGame() {
const [board, setBoard] = useState<Cell[]>([...emptyBoard]);
const [isPlayerTurn, setIsPlayerTurn] = useState(true);
const [winner, setWinner] = useState<Player | 'Draw' | null>(null);
useEffect(() => {
if (!isPlayerTurn && !winner) {
const move = minimax([...board], true).index;
if (move !== -1) {
const newBoard = [...board];
newBoard[move] = 'O';
setBoard(newBoard);
setWinner(checkWinner(newBoard));
setIsPlayerTurn(true);
}
}
}, [isPlayerTurn, board, winner]);
const handleClick = (index: number) => {
if (board[index] || winner || !isPlayerTurn) return;
const newBoard = [...board];
newBoard[index] = 'X';
setBoard(newBoard);
setWinner(checkWinner(newBoard));
setIsPlayerTurn(false);
};
const resetGame = () => {
setBoard([...emptyBoard]);
setWinner(null);
setIsPlayerTurn(true);
};
return (
<Container maxWidth="sm" sx={{ mt: 5 }}>
<Typography variant="h4" align="center" gutterBottom>
Tic Tac Toe
</Typography>
<Grid container spacing={1} >
{board.map((cell, idx) => (
<Grid key={idx} size={4}>
<Paper
elevation={3}
sx={{
height: 100,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '2rem',
cursor: cell || winner || !isPlayerTurn ? 'default' : 'pointer',
backgroundColor: 'background.paper',
}}
onClick={() => handleClick(idx)}
>
{cell}
</Paper>
</Grid>
))}
</Grid>
{winner && (
<Box mt={4} textAlign="center">
<Typography variant="h5" gutterBottom>
{winner === 'Draw' ? "It's a draw!" : `${winner} wins!`}
</Typography>
<Button variant="contained" onClick={resetGame}>
Play Again
</Button>
</Box>
)}
</Container>
);
}

View File

@ -0,0 +1 @@
export * from './Xo';