The answer to your original question before you edited it was this simple query with MAX with GROUP BY:
SELECT 
    OrderId, 
    MAX(Code) AS Code
FROM yourtable
GROUP BY OrderId
ORDER BY OrderId;
If according to your new requirements further columns should be selected, we could use the above query as subquery with JOIN:
SELECT 
    y.OrderId, 
    y.Code, 
    y.Val
FROM yourtable y
INNER JOIN (
    SELECT 
        OrderId, 
        MAX(Code) AS Code
    FROM yourtable
    GROUP BY OrderId
) AS sub ON y.OrderId = sub.OrderId
    AND y.Code = sub.Code
ORDER BY y.OrderId;
But this becomes long and bad to read. Therefore using a window function should be prefered.
But there is another possible issue which should be solved:
We should be careful with this simple MAX or ROW_NUMBER ideas if lots of codes per OrderId can appear because the above query will for example fetch Code2, not Code10 as highest code if both appear. That's because it's a string, not a number.
I guess that's not intended. We can fix this issue by finding out the highest number after the word code. So we could do something like this here, using SUBSTRING and ROW_NUMBER:
SELECT orderId, code, val
FROM (
  SELECT 
    orderId, code, val,
    ROW_NUMBER() OVER 
      (PARTITION BY orderId 
      ORDER BY CAST(SUBSTRING(Code,5,LEN(code)-4) AS INT) DESC) row_num
    FROM yourtable
) Orders
WHERE row_num = 1;
Thus, Code10 will be taken rather than Code2.
We can replicate these things here: db<>fiddle
The idea with the longer query is also shown in the fiddle, but as said this is unhandy and bad to read, so I don't recommend it.