├── assets ├── css │ └── style.css └── js │ ├── game.js │ └── possibilities.js ├── favicon.svg ├── index.html └── readme.md /assets/css/style.css: -------------------------------------------------------------------------------- 1 | [type=text],[type=email],[type=url],[type=password],[type=number],[type=date],[type=datetime-local],[type=month],[type=search],[type=tel],[type=time],[type=week],[multiple],textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem}[type=text]:focus,[type=email]:focus,[type=url]:focus,[type=password]:focus,[type=number]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=month]:focus,[type=search]:focus,[type=tel]:focus,[type=time]:focus,[type=week]:focus,[multiple]:focus,textarea:focus,select:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);border-color:#2563eb}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 2px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);border-color:#6b7280}[type=checkbox]:checked,[type=radio]:checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:checked:hover,[type=checkbox]:checked:focus,[type=radio]:checked:hover,[type=radio]:checked:focus{border-color:transparent;background-color:currentColor}[type=checkbox]:indeterminate:hover,[type=checkbox]:indeterminate:focus{border-color:transparent;background-color:currentColor}*,:before,:after{-webkit-box-sizing:border-box;box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}*{--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgba(59, 130, 246, .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000}:root{-moz-tab-size:4;-o-tab-size:4;tab-size:4}:-moz-focusring{outline:1px dotted ButtonText}:-moz-ui-invalid{box-shadow:none}::moz-focus-inner{border-style:none;padding:0}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[multiple]{background-image:initial;background-position:initial;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;color-adjust:unset}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")}[type=radio]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e")}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}a{color:inherit;text-decoration:inherit}body{margin:0;font-family:inherit;line-height:inherit}button{font-family:inherit;font-size:100%;line-height:1.15;margin:0;text-transform:none;background-color:transparent;background-image:none;padding:0;line-height:inherit;color:inherit}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button,[role=button]{cursor:pointer}html{-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5}h1{margin:0;font-size:inherit;font-weight:inherit}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}select{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;color-adjust:exact}.container{width:100%;margin-left:auto;margin-right:auto}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.bg-dark-500{--tw-bg-opacity: 1;background-color:rgba(31,31,31,var(--tw-bg-opacity))}.hover\:bg-red-700:hover{--tw-bg-opacity: 1;background-color:rgba(185,28,28,var(--tw-bg-opacity))}.bg-gradient-to-bl{background-image:-o-linear-gradient(top right,var(--tw-gradient-stops));background-image:-webkit-gradient(linear,right top,left bottom,from(var(--tw-gradient-stops)));background-image:linear-gradient(to bottom left,var(--tw-gradient-stops))}.from-green-400{--tw-gradient-from: rgba(52, 211, 153, var(--tw-from-opacity, 1));--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgba(255, 255, 255, 0))}.to-blue-500{--tw-gradient-to: rgba(59, 130, 246, var(--tw-to-opacity, 1))}.border-white{--tw-border-opacity: 1;border-color:rgba(255,255,255,var(--tw-border-opacity))}.rounded{border-radius:.25rem}.border-1{border-width:1px}.flex{display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.flex-col{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.justify-center{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.font-bold{font-weight:700}.h-screen{height:100vh}.h-20{height:5rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.m-auto{margin:auto}.mx-auto{margin-left:auto;margin-right:auto}.mt-10{margin-top:2.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.pt-30{padding-top:7.5rem}.pt-10{padding-top:2.5rem}.text-center{text-align:center}.text-white{--tw-text-opacity: 1;color:rgba(255,255,255,var(--tw-text-opacity))}.uppercase{text-transform:uppercase}.w-20{width:5rem}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50;margin-top:60px} 2 | -------------------------------------------------------------------------------- /assets/js/game.js: -------------------------------------------------------------------------------- 1 | const wordle = { 2 | todaysWord: possibilities[Math.floor((new Date() - new Date(2022, 0, 0)) / 8.64e7)], 3 | currentWordPosition: 0, 4 | offset: 0, 5 | offsetLock: 0, 6 | gameOver: false, 7 | showResult: false, 8 | locked: false, 9 | words: new Array(5).fill(null).map((x) => new Array(5).fill(null).map((x) => ({ value: "", match: false }))), 10 | 11 | getCurrentWordPosition() { 12 | //return current word array position 13 | return Math.floor(this.offset / 5) 14 | }, 15 | 16 | clearCurrentWord() { 17 | //clear the current word in case of an invalid entry 18 | this.offset -= 5 19 | this.words[this.currentWordPosition].map((x) => { 20 | x.match = false 21 | x.value = "" 22 | }) 23 | }, 24 | 25 | processKey(event) { 26 | //process the keystrokes 27 | if (this.gameOver && event.key == "Enter") { 28 | this.restart() 29 | } 30 | 31 | if (this.gameOver || this.locked) { 32 | //no more keystroke processing if in locked state or if the game is over 33 | return 34 | } 35 | 36 | if (event.key == "Backspace") { 37 | //remove the last entered letter 38 | if (this.offset == this.offsetLock) { 39 | return 40 | } 41 | this.offset-- 42 | this.currentWordPosition = this.getCurrentWordPosition() 43 | 44 | this.words[this.currentWordPosition][this.offset % 5].value = "" 45 | } 46 | 47 | if ("abcdefghijklmnopqrstuvwxyz".includes(event.key)) { 48 | //ok it's a valid alpha input 49 | this.currentWordPosition = this.getCurrentWordPosition() 50 | this.words[this.currentWordPosition][this.offset % 5].value = event.key 51 | if (this.offset % 5 == 4) { 52 | //current word array is filled up, so check if the entry matched 53 | this.match() 54 | } 55 | this.offset++ 56 | 57 | if (this.offset == 25) { 58 | //input complete for all letters, game is over 59 | this.gameOver = true 60 | return 61 | } 62 | } 63 | }, 64 | 65 | match() { 66 | //process the current entry word 67 | this.offsetLock = this.currentWordPosition * 5 + 5 68 | const _words = this.words[this.currentWordPosition].map((x) => x.value) 69 | const _word = _words.join("") 70 | if (possibilities.includes(_word)) { 71 | //ok its a valid word 72 | for (index = 0; index < 5; index++) { 73 | if (this.todaysWord.includes(_words[index])) { 74 | //ok the letter is found somewhere - so it's a match. But is it an exact match? let's find out 75 | this.words[this.currentWordPosition][index].match = true 76 | if (this.todaysWord.indexOf(_words[index]) == index) { 77 | //ok, even the offset of this letter is matched - so it's an exact match 78 | this.words[this.currentWordPosition][index].exactMatch = true 79 | } 80 | } 81 | } 82 | 83 | if (this.todaysWord == _word) { 84 | //all letters matched 85 | this.gameOver = true 86 | } 87 | } else { 88 | //not a valid word - so clean the word 89 | this.locked = true //show the message 90 | let that = this 91 | setTimeout(function () { 92 | that.clearCurrentWord() 93 | that.locked = false 94 | that.gameOver = false 95 | that.showResult = false 96 | }, 1000) 97 | } 98 | }, 99 | 100 | restart() { 101 | //restart the game 102 | this.words = new Array(5).fill(null).map((x) => new Array(5).fill(null).map((x) => ({ value: "", match: false }))) 103 | this.offset = 0 104 | this.currentWordPosition = 0 105 | this.gameOver = false 106 | this.showResult = false 107 | }, 108 | } 109 | -------------------------------------------------------------------------------- /favicon.svg: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 |